Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # =============================================================================
- # Задание 1. Создание массива. Добавление элементов. Удаление элементов.
- # Срезы массива. Цикл по массиву.
- # =============================================================================
- # В Python массивов нет, они называются списками. Но в общем, то же самое.
- # Создаём.
- my_list = [42, 5, "Hello, World"]
- # Добавляем в него ещё один элемент (в конец)
- my_list.append("Привет") # [42, 5, "Hello, World", "Привет"]
- # Добавляем его самого в себя
- my_list.append(my_list) # [42, 5, "Hello, World", "Привет", [...]]
- # Получаем срез из элементов от первого до третьего (не включая третий!!!)
- my_list2 = my_list[1:3] # [5, "Hello, World"]
- # Удаляем первый попавшийся элемент "Hello, World"
- my_list.remove("Hello, World")
- # Следующая строка вызовет исключение, потому что элемента 777
- # нет в нашем массиве
- my_list.remove(777)
- # Цикл по массиву.
- # Цикл for в Пайтоне отличается от циклов for в других языках, и является тем,
- # что в других языках называется циклом foreach. Классического for в Пайтоне
- # нет.
- my_list = [2, 5, 10, -5, 100]
- for x in my_list:
- print(x**2) # **2 - возведение в квадрат
- # Результат:
- # 4
- # 25
- # 100
- # 25
- # 10000
- # =============================================================================
- # Задание 2. Задание функций. Вызов функций. Декораторы.
- # =============================================================================
- # Задаём функцию от двух переменных
- def my_function(x, y):
- print(x + y)
- # Вызываем её
- my_function(5, 10) # Выведет на экран 15
- # Задаём функцию, возвращающую значение, с параметром по умолчанию
- def my_function(x, y=42):
- return x - y
- # Вызываем её
- print(my_function(15, 10)) # Выведет на экран 5
- print(my_function(43)) # Выведет на экран 1
- # В Питоне всё есть объект класса. Даже любой класс является объектом класса.
- # Типы данные отсутствуют, начиная с Python 3 они называются классами данных.
- # Функция - тоже объект. Её можно поместить в массив, её можно передать
- # в качестве аргумента, её можно вернуть из другой функции.
- # Создадим функцию от двух функций f и g, которая будет возвращать функцию,
- # возвращающую произведение возвращаемых значений функций f и g.
- # На примере будет понятнее.
- def create_function(f, g):
- def new_function(x):
- return f(x) * g(x)
- return new_function
- # Зададим функции f и g
- def f(x):
- return x**2
- def g(x):
- return x / 2
- # Вызываем всё это
- print(create_function(f, g)(5)) # create_function(f, g) вернёт функцию. Мы эту
- # функцию сразу вызываем с аргументом 5.
- # Выведет на экран 62.5, т.е. (5**2)*(5/2) = 25*2.5 = 62.5
- # Переходим к декораторам. Зададим следующую функцию
- def create_func(old_func):
- def new_func(x):
- return old_func(x) + 5
- return new_func
- # Чем-то похоже на предыдущий пример? Теперь функция my_func (строчка I)
- def my_func(x):
- return x**3
- # Теперь рассмотрим такую запись (II):
- my_func = create_func(my_func)
- # Т.е. мы заменили функцию, хранящуюся в переменной my_func, на новую функцию,
- # которую вернула функция create_func
- # Вызовем my_func
- my_func(10) # Вернёт 1005, т.е. 10**3 + 5
- # Теперь представим, что мы не выполняли строчки (I) и (II), а вместо этого
- # использовали функцию create_func в качестве декоратора при объявлении
- # функции my_func:
- @create_func
- def my_func(x):
- return x**3
- # Получится то же самое. Функция my_func сразу после объявления будет передана
- # в декоратор create_func, а то, что вернёт декоратор, запишется в переменную
- # my_func вместо оригинальной функции.
- # Ещё примерчик с декоратором
- my_list = []
- def my_decorator(f):
- my_list.append(f)
- return f
- @my_decorator
- def my_func(x, y):
- return x * y
- # В результате выполнения вышестоящих строк в массиве my_list окажется функция.
- # my_list[0] и переменная my_func есть, по сути, две ссылки на один и тот же
- # объект, которым является функция.
- my_list[0](2, 3) # Вернёт 6.
- # =============================================================================
- # Задание 3. Выдать сообщение игроку после его смерти
- # =============================================================================
- from events import Event
- from messages import SayText2
- from players.entity import Player
- # Создаём объект класса SayText2. Сообщение одинаковое будет во всех случаях,
- # поэтому я создаю его заранее, чтобы по 100500 раз не создавать его внутри
- # события.
- MESSAGE = SayText2("You are dead.")
- # Знакомтесь. Декоратор Event(<название события>). Замечу, что декоратор тут не
- # Event, а то, что вернёт Event(<название события>).
- # Декоратор Event(<название события>) цепляет входную функцию к менеджеру
- # событий и возвращает... ту же самую функцию. Вся его роль только в
- # регистрации функции. Данный декоратор позаботится о том, чтобы функция
- # была "отцеплена" от менеджера событий при выгрузке плагина из памяти.
- # Декораторы используются в SP повсеместно.
- @Event('player_death')
- def on_player_death(game_event): # имя функции может быть любым, я предпочитаю
- # формат on_<название события>
- # В словаре game_event (название произвольное) хранятся переменные события
- # Обращение как к любому словарю: словарь['ключ']
- # Player - универсальный класс для игрока, наследуется от класса Entity
- # В общем случае он, как и класс Entity, строится так:
- # >> player = Player(index)
- # где index - индекс энтити игрока.
- # Но у самого класса Player есть волшебный метод from_userid, который
- # принимает userid и возвращает уже построенный объект класса Player.
- player = Player.from_userid(game_event['userid'])
- # К слову, всё, что делает метод from_userid:
- # >> def from_userid(userid):
- # >> return Player(index_from_userid(userid))
- # Функция-помощник под названием index_from_userid импортируется из модуля
- # players.helpers:
- # >> from players.helpers import index_from_userid
- # Но зачем лишний раз импортировать, если можно воспользоваться методом
- # Player.from_userid?
- # Теперь отправляем сообщение. Отправляется оно по индексу игрока.
- # Индекс любого объекта класса Entity получается так:
- # >> object.index
- # В нашем случае объект класса Entity (если конкретнее, класса Player)
- # вернёт свой индекс так:
- # >> player.index
- MESSAGE.send(player.index)
- # =============================================================================
- # Задание 4. Форматирование строк
- # =============================================================================
- "{0} says {1}".format("iPlayer", "Hello") # подстановка аргументов по их
- # номеру
- # Результат: "iPlayer says Hello"
- "{} says {}".format("iPlayer", "Hello") # номера можно опустить, если
- # аргументы подставляются по
- # порядку
- # Результат: "iPlayer says Hello"
- "{player} says {word}".format(player="iPlayer", word="Hello")
- # Результат: "iPlayer says Hello"
- keywords = ["iPlayer", "Hello"]
- "{} says {}".format(*keywords) # разворачивание списка в аргументы функции
- # Результат: "iPlayer says Hello"
- keywords = {'player': "iPlayer", 'word': "Hello"}
- "{player} says {word}".format(**keywords) # разворачивание словаря в
- # именованные аргументы функции
- # =============================================================================
- # Задание 5. Печатать топ-3 игроков, набравших больше всего убийств,
- # в конце раунда
- # =============================================================================
- from events import Event
- from filters.players import PlayerIter
- from listeners import OnClientActive, OnClientDisconnect
- from messages import SayText2
- from players.entity import Player
- from players.helpers import index_from_userid
- # Заводим ассоциативный массив (он же словарь) players. Ключами будут выступать
- # индексы игроков, а значениями - количество убийств в раунде
- players = {}
- # Функция load в главном файле плагина в текущей версии Source.Python
- # вызывается при загрузке плагина.
- # Нам эта функция понадобится, чтобы занести в наш словарь игроков, которые уже
- # играют на сервере в момент загрузки плагина (ситуация "горячий старт")
- def load():
- # Итерируем (проходим) по всем игрокам на сервере.
- # Генератор PlayerIter() будет возвращать новый объект класса Player на
- # каждой итерации.
- for player in PlayerIter():
- players[player.index] = 0
- @OnClientActive
- def listener_on_client_active(index):
- players[index] = 0
- @OnClientDisconnect
- def listener_on_client_disconnect(index):
- # Когда игрок отключается во время подключения, может возникнуть ситуация,
- # при которой OnClientDisconnect сработает без срабатывания OnClientActive.
- # Поэтому может оказаться, что индекс отключаемого игрока отсутствует в
- # нашем словаре. Чтобы избежать исключений, с помощью оператор in я
- # делаю проверку, есть ли индекс среди ключей нашего словаря.
- if index in players:
- # Теперь, когда мы убедились, что индекс присутствует, надо его удалить
- del players[index]
- @Event('round_start')
- def on_round_start(game_event):
- # В начале нового раунда следует сбросить счётчики убийств.
- # players.keys() - генератор ключей нашего словаря.
- for index in players.keys():
- players[index] = 0
- @Event('player_death')
- def on_player_death(game_event):
- # Если userid нападавшего равен нулю, то нападавший - не игрок. Выходим из
- # обработчика события.
- if game_event['attacker'] == 0:
- return
- # Заодно не будем считать самоубийства
- if game_event['attacker'] == game_event['userid']:
- return
- # Превращаем userid нападавшего в индекс
- index = index_from_userid(game_event['attacker'])
- # Добавляем единичку к счётчику убийств нападавшего
- players[index] += 1
- @Event('round_end')
- def on_round_end(game_event):
- # Сортируем индексы по количеству убийств хозяина с помощью встроенной
- # в Пайтон функции sorted
- sorted_player_indexes = sorted(
- # Сортировать будем индексы, т.е. ключи нашего словаря
- players.keys(),
- # В качестве задающей сортировку функции будем использовать
- # лямбда-функцию (анонимную однострочную функцию), которая будет
- # принимать на вход ключ словаря и возвращать соответствующее значение
- # (т.е. сортировка пойдёт по значениям словаря - убийствам)
- key=lambda index: players[index],
- # Необязательный параметр reverse позволяет произвести сортировку в
- # обратном порядке. По умолчанию (без него) сортировка идёт по
- # возрастанию, а нам нужно по убыванию.
- reverse=True,
- )
- # В результате в списке sorted_player_indexes хранятся индексы,
- # отсортированные по количеству соответствующих убийств в порядке убывания
- # Берём первые три индекса (пропустив первую координату среза, я тем самым
- # заставляю срез начинаться с самого начала списка - можно было
- # использовать [0:3])
- sorted_player_indexes = sorted_player_indexes[:3]
- # Сюда будем складывать имена игроков
- player_names = []
- for index in sorted_player_indexes:
- player_names.append(Player(index).name)
- # Составляем текст сообщения
- text = "TOP-3 players: 1) {}, 2) {}, 3) {}".format(*player_names)
- # Создаём и отправляем SayText2 (вызов метода send без параметров приводит
- # к отправке сообщения всем игрокам на сервере)
- SayText2(text).send()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement