11 subscribers
38 photos
2 links
Download Telegram
first_name = 'Сильвестр'
last_name = 'Сталлоне'
print(actors[first_name + ' ' + last_name])

Если ключа в словаре нет, возникнет ошибка:

print(actors['Несуществующий ключ'])
KeyError: 'Несуществующий ключ'
Удаление, добавление элементов в словари:
6. Нестроковые ключи
Решим следующую задачу. Пусть дан длинный список целых чисел numbers. Мы знаем, что некоторые числа встречаются в этом списке несколько раз. Нужно узнать, сколько именно раз встречается каждое из чисел.

numbers = [1, 10, 1, 6, 4, 10, 4, 2, 2, 1, 10, 1]
counts = {}
for number in numbers:
if number not in counts:
counts[number] = 1
else:
counts[number] += 1


Просто так сделать counts[number] += 1 нельзя: если ключа number в словаре нет, возникнет ошибка KeyError.

В результате работы этой программы все элементы из списка numbers окажутся ключами словаря counts. Значением counts[x] будет количество раз, которое число x встретилось в списке numbers. Как это работает?

Цикл for перебирает все элементы списка numbers и для каждого проверяет, присутствует ли он уже в качестве ключа в counts. Если нет — значит, число встретилось нам впервые и мы инициализируем значение counts[numbers] = 1. Иначе увеличим counts[number] на единицу, поскольку число number встретилось нам повторно.

Почему для этой задачи не стоит использовать список, хотя ключи — обычные целые числа? Потому что, используя словарь, мы можем решить эту задачу и для вещественных чисел, и для очень больших целых чисел, и вообще для любых объектов, которые можно сравнивать.
list(map(int, input().split())))
Возврат из глубины функции
Множественные точки возврата из функции позволяют нам упростить обработку и более сложных структур, например, вложенных списков. Наша следующая программа будет проверять, есть ли в матрице элемент, отличающийся от искомого не больше чем на число eps.

Матрица записывается как список списков. Мы предполагаем, что наша функция будет работать с большими матрицами, поэтому нам не хочется тратить лишнее время на проверку. Мы будем прекращать поиск, как только нашли подходящий элемент. Давайте для начала разберемся, как бы мы действовали без множественных операторов return.

def matrix_has_close_value(matrix, value, eps):
found = False
for row in matrix:
for cell in row:
if abs(cell - value) <= eps:
found = True
break
if found:
break
if found:
return True
else:
return False

Как видите, нам приходится прилагать некоторые усилия, чтобы выйти из нескольких уровней вложенности. Каждый уровень вложенности — дополнительное препятствие на пути к завершению функции. Ему мешают не только циклы, как в этом примере, но и условные операторы.

Перепишем теперь функцию с учетом того, что, как только мы нашли элемент, мы уже знаем, что ответ — True (т. е. элемент содержится в матрице). А если мы закончили перебор элементов и так и не нашли ни одного элемента, ответ False.

def matrix_has_close_value(matrix, value, eps):
for row in matrix:
for cell in row:
if abs(cell - value) <= eps:
return True
return False

Хотя return False не заключен ни в какое условие, выполняется он только тогда, когда элемент не найден. Если элемент найден, мы сразу выходим из функции и до этой строки просто не доходим. Оператор return очень удобен, когда нужно выйти из глубины функции.
Возврат нескольких значений
В задаче про корни квадратного уравнения у нас уже возникала необходимость вернуть несколько значений. Вы видели, что это можно сделать, вернув список значений.

То же самое можно сделать немного проще: если после return написать несколько значений через запятую, Python автоматически поместит эти значения в кортеж и вернет этот кортеж.

def get_coordinates():
return 1, 2


print(get_coordinates())
# => (1, 2)
Мы разобрались, как возвращать значения из функции. Но как программа их получает, когда значений несколько? Оказывается, есть несколько способов. Один вариант вы знаете, можно записать в переменную весь кортеж:

def get_coordinates():
return 1, 2


result = get_coordinates()
print(result)
# => (1, 2)


Можно вместо этого воспользоваться множественным присваиванием, тогда значения автоматически будут распределены по разным переменным:

x, y = get_coordinates()
print(x) # => 1
print(y) # => 2
Аннотация типов
Python — язык с динамической типизацией. Это означает, что типы связаны со значением переменной, а не с ней самой. Переменные могут принимать любое значение в любой момент и проверяются только перед выполнением операций над ними.

Однако, при написании кода, мы так или иначе предполагаем переменные каких типов будут использоваться (это может быть вызвано ограничением алгоритма или логики). Для корректной работы программы нам важно как можно раньше найти ошибки, связанные с передачей данных неверного типа.

Аннотации типов — это новая возможность, описанная в PEP484, которая позволяет добавлять подсказки о типах переменных. Они используются, чтобы информировать читателя кода, каким должен быть тип переменной.

Аннотации типов не влияют на время выполнения программы. Эти подсказки игнорируются интерпретатором и используются исключительно для повышения удобочитаемости для других программистов и вас самих. Аннотации типов поддерживаются многими IDE для Python, которые выделяют некорректный код или выдают подсказки в процессе набора текста.

Для создания аннотированных переменных можно использовать один из способов:

count = 5 # type: int
count: int; count = 5
count: int = 5

В первой строке тип переменной указываем в комментариях. В двух других строках тип переменной указываем в коде, через двоеточие от имени переменной и дальше двумя разными способами задаем значение переменной.

Для аннотирования списоков, кортежей, словарей и множеств используют имена классов.

my_list: list
my_tuple: tuple
my_dic: dict
my_set: set

Такое аннотирование не слишком информативно, поскольку не показывает, какого типа элементы содержатся внутри.

Что бы показать тип элементов его указывают внутри квадратных скобок:

my_list: list[int]
my_tuple: tuple[str, float, float]
my_dic: dict[str, int]
my_set: set[str]


Удобнее всего использовать аннотации типов при описании функции: можно указать типы аргументов и тип ожидаемого результата или что-то одно. Аргумент аннотируется через двоеточие после имени, а возвращаемое значение через -> после имени и аргументов функции.

def double_it(x: int) -> int:
return x * 2


def get_coordinates() -> tuple:
return 1, 2


def greet_all(names: list[str]) -> None:
for name in names:
print("Hello", name)
Python
Photo
можно записать переменную с * внутрь которой попадут все "незадействованные" элементы
без * перед func(—>t) код не будет работать требуя значения ещё и для b, c т.к. t это кортеж и он будет полностью записываться в a, * — нужна для распаковки t
Аргументы по умолчанию
Бывает так, что какой-то параметр функции часто принимает одно и то же значение.

Например, хорошо известная вам функция int принимает два параметра: строка, которую нужно преобразовать в число, а также основание системы счисления. Это позволяет ей считывать числа в различных системах счисления, например, двоичное число 101 мы можем считать так:

int('101', 2) # => 5
Но чаще всего эта функция используется для считывания из строки чисел, записанных в десятичной системе счисления. Было бы неудобно каждый раз писать 10 вторым аргументом. На такой случай Python позволяет задавать некоторым аргументам значения по умолчанию. У функции int второй аргумент по умолчанию равен 10, и потому можно вызывать эту функцию с одним аргументом. Значение второго подставится автоматически.
Позиционные и именованные аргументы

Аргументы, которые передаются без указания имен, называются позиционными, потому что функция по положению аргумента понимает, какому параметру он соответствует. Аргументы, которые передаются с именами, называются именованными.

Типо как print(1, 2, 3) # => a b c
и print(1, 2, 3, sep=' ') # => a b c
Python
Позиционные и именованные аргументы Аргументы, которые передаются без указания имен, называются позиционными, потому что функция по положению аргумента понимает, какому параметру он соответствует. Аргументы, которые передаются с именами, называются именованными.…
Если вы укажете только одно дополнительное значение, оно будет присвоено первому аргументу по умолчанию, а второй аргумент так и останется со значением по умолчанию. Если укажете два значения, значения будут присвоены обеим переменным.
Использование map:
numbers = range(1, 10)
squared_numbers = list(map(lambda x: x ** 2, numbers))
print(squared_numbers) # [1, 4, 9, 16, 25, 36, 49, 64, 81]

Функция map применяет lambda x: x ** 2 к каждому числу, возводя его в квадрат.