Python Урок 3. Функции и процедуры
![]()
Пример: Создать процедуру для вывода сообщения об ошибке. Запрашивать у пользователя ввести положительное число, в случае ввода отрицательного числа, вызывать процедуру для вывода сообщения об ошибке.
def Err(): # определение процедуры print ( "Ошибка: неверные данные" ) n = int ( input('введите положительное число') ) if n 0: Err() # вызов процедуры
def Err(): # определение процедуры print ( «Ошибка: неверные данные» ) n = int ( input(‘введите положительное число’) ) if n < 0: Err() # вызов процедуры
- Процедура — вспомогательный алгоритм, выполняющий некоторые действия.
- Это поименованный фрагмент программы, который можно вызвать.
- Процедура должна быть определена к моменту её вызова. Определение процедуры начинается со служебного слова def.
- Вызов процедуры осуществляется по ее имени, за которым следуют круглые скобки, например, Err().
- В одной программе может быть сколько угодно много вызовов одной и той же процедуры.
- Использование процедур сокращает код и повышает удобочитаемость.
Процедура с параметрами
Как используются в Python параметры процедуры, рассмотрим на примере.
Пример: Написать процедуру, которая печатает 60 раз указанный символ (введенный с клавиатуры), каждый с новой строки.
1 2 3 4 5
def printChar(s): for i in range(60): print (s) sim = input('введите символ') printChar(sim)
def printChar(s): for i in range(60): print (s) sim = input(‘введите символ’) printChar(sim)
- Глобальная переменная — если ей присвоено значение в основной программе (вне процедуры).
- Локальная переменная (внутренняя) известна только на уровне процедуры, обратиться к ней из основной программы и из других процедур нельзя.
- Параметры процедуры — локальные переменные. В программе s — локальная переменная.
Задание Python 3_0:
Создать процедуру, которая вычисляет разность двух вводимых пользователем числа. Выполнить задание двумя способами: 1) процедура без параметров: числа — глобальные переменные, определенные в основной программе; 2) процедура с параметрами: числа — параметры процедуры.
Локальные и глобальные переменные
Примеры использования локальных и глобальных переменных:
1 2 3 4
x = 3 # глобальная переменная def pr(): # процедура без параметров print (x) # вывод значения глобальной переменной pr()
x = 3 # глобальная переменная def pr(): # процедура без параметров print (x) # вывод значения глобальной переменной pr()
1 2 3 4 5
x = 3 # глобальная переменная def pr(a): # процедура с параметром a = 4 # локальная переменная print (a) # 4 pr(x) # передача параметра глобальной переменной (3)
x = 3 # глобальная переменная def pr(a): # процедура с параметром a = 4 # локальная переменная print (a) # 4 pr(x) # передача параметра глобальной переменной (3)
1 2 3 4 5 6
x = 3 # глобальная переменная def pr(): # процедура без параметров global x x = 1 print (x) # вывод измененного значения глобальной переменной (1) pr(x)
x = 3 # глобальная переменная def pr(): # процедура без параметров global x x = 1 print (x) # вывод измененного значения глобальной переменной (1) pr(x)
Задание Python 3_1:
Напишите процедуру, которая выводит на экран в столбик все цифры переданного ей числа, начиная с последней:
число: 4673 результат: 3 7 6 4
Задание Python 3_2:
Напишите процедуру, которая выводит на экран все делители переданного ей числа (в одну строчку).
Задание Python 3_3:
Составить программу с процедурой для вычисления степени числа (входные параметры: число и степень).
Рекомендации: для вычисления степени числа можно использовать функцию pow(число, степень)
Задание Python 3_4:
Напишите процедуру, которая принимает параметр – натуральное число N – и выводит первые N чисел Фибоначчи.
Пример использования ключевого слова global :
Поменять значений двух переменных.
def Swap(): global x,y t = x x = y y = t x=3 y=5 Swap() print(x,y)
def Swap(): global x,y t = x x = y y = t x=3 y=5 Swap() print(x,y)
def Swap(): global x,y (x, y) = (y, x) (x,y)=(3,5) Swap() print(x,y)
def Swap(): global x,y (x, y) = (y, x) (x,y)=(3,5) Swap() print(x,y)
Задание Python 3_5:
Создайте процедуру без параметров AddLeftDigit() , которая добавляет введенную цифру K (0 D (0 global для работы с глобальными переменными.
Ожидаемый результат:
введите D (0<=D<=9) и K(0<=K<=9): >>>2 >>>4 результат: 42
Язык Python функции
Часть функций языка Python являются встроенными функциями, которые обеспечены синтаксисом самого языка. Например, int, input, randint.
Рассмотрим пример создания пользовательских функций.
- Функция — это поименованный фрагмент программы, который можно вызвать.
- Как и процедура, функция должна быть определена к моменту её вызова (служебное слово def).
- Функция в отличии от процедуры возвращает значение.
- Для возврата значения функции используется оператор return.
- Вызов функции осуществляется по ее имени и обычно сопровождается выводом значения.
Пример:
Найти максимальное значение из значений двух переменных.
def max(a,b): if(a>b): return a else: return b x=int(input()) y=int(input()) print('max = ',max(x,y))
def max(a,b): if(a>b): return a else: return b x=int(input()) y=int(input()) print(‘max = ‘,max(x,y))
Задание Python 3_6:
Создайте функцию для поиска минимума среди трех чисел (три параметра функции).
Пример:
Вычислить сумму цифр числа.
1 2 3 4 5 6 7 8
def sumD(n): # определение функции с параметром sum = 0 while n!= 0: sum += n % 10 n = n // 10 return sum # возврат значения функции # основная программа print (sumD(1075)) # вызов функции с параметром
def sumD(n): # определение функции с параметром sum = 0 while n!= 0: sum += n % 10 n = n // 10 return sum # возврат значения функции # основная программа print (sumD(1075)) # вызов функции с параметром
Задание Python 3_7:
Напишите функцию, которая вычисляет количество цифр числа.
Задание Python 3_8:
Создайте функцию, которая вычисляет сумму всех чисел от 1 до N . N — параметр функции.
Кто в Python должен проверять, правильного ли типа аргументы передаются в функцию или метод?
Например, если в функцию (для примера) мы передадим не iterable, а целое или вещественное число, то сгенерируется исключение TypeError (т.к. int и float не iterable). Но можно же в самом начале самому явно проверить, например, что переданный аргумент является итерируемым объектом и что-то сгенерировать.
def is_positive_or_zero_values(iterable): """Проверить все ли элементы в iterable есть числа равные или больше нуля. Args: iterable: итерируемый объект, содержащий значения на проверку. Returns: bool: True, если все элементы в iterable есть числа, которые равные или больше нуля.. False, иначе. """ if iterable: if is_numbers(iterable): return all(map(lambda x: x >= 0, iterable)) else: return False else: return False
5.1. Теория¶
Подпрограмма — средство языка программирования, позволяющее упаковывать и параметризовать функциональность.
Как правило, подпрограмма — это именованный фрагмент программного кода, к которому можно обратиться из другого места программы, однако она может и не иметь имени (называясь в таком случае анонимной).
5.1.1. Основные понятия и механизм работы¶
5.1.1.1. Определение подпрограммы¶
Подпрограмма должна быть объявлена и в общем случае содержать:
- имя;
- список имен и типов передаваемых параметров (необязательно);
- тип возвращаемого значения (необязательно).
Если подпрограмма возвращает значение вызывающему коду (одно или несколько), она называется функцией, иначе — процедурой.
5.1.1.2. Вызов подпрограммы¶
Для того, чтобы использовать ранее определенную подпрограмму, необходимо в требуемом месте кода произвести ее вызов, указав:
- указать имя подпрограммы;
- передать требуемые аргументы (значения параметров).
Код, вызвавший подпрограмму, передает ей управление и ожидает завершения выполнения.
Подпрограмма также может вызывать сама себя, т.е. выполняться рекурсивно.
В настоящее время наиболее часто встречаются следующие способы передачи аргументов:
Для переменной, переданной по значению создается локальная копия и любые изменения, которые происходят в теле подпрограммы с переданной переменной, на самом деле, происходят с локальной копией и никак не сказываются на самой переменной.
Изменения, которые происходят в теле подпрограммы с переменной, переданной по ссылке, происходят с самой переданной переменной.
5.1.1.3. Механизм работы¶
Большинство современных языков программирования для управления вызовом подпрограмм используют стек вызовов.
Примерный цикл работы стека вызова следующий (Видео 5.1.1, Видео 5.1.2):
- Вызов подпрограммы создает запись в стеке; каждая запись может содержать информацию о данных вызова (аргументах, результате, а также адресе возврата).
- Когда подпрограмма завершается, запись удаляется из стека и программа продолжает выполняться, начиная с адреса возврата.
Видео 5.1.1 — Cтек вызовов (пример, Нетология)
Your browser does not support the video tag.
Видео 5.1.2 — Cтек вызовов (пример, Stepik.org)
5.1.1.4. Преимущества и недостатки¶
Главное назначение подпрограмм сегодня — структуризация программы с целью удобства ее понимания и сопровождения.
Преимущества использования подпрограмм:
- декомпозиция сложной задачи на несколько более простых подзадач: это один из двух главных инструментов структурного программирование (второй — структуры данных);
- уменьшение дублирования кода и возможность повторного использования кода в нескольких программах — следование принципу DRY «не повторяйся» (англ.Don’t Repeat Yourself);
- распределение большой задачи между несколькими разработчиками или стадиями проекта;
- сокрытие деталей реализации от пользователей подпрограммы;
- улучшение отслеживания выполнения кода (большинство языков программирования предоставляет стек вызовов подпрограмм).
Недостатком использования подпрограмм можно считать накладные расходы на вызов подпрограммы, однако современные трансляторы стремятся оптимизировать данный процесс.
5.1.2. Функции в Python¶
В Python нет формального разделения подпрограмм на функции и процедуры (как, например, в Паскале или Си), и процедурой можно считать функцию, возвращающую пустое значение — в остальном используется единственный термин — функция.
Для объявления функции в Python используется ключевое слово def :
def function_name([parameters]): # `parameters`: параметры функции (через запятую) suite # Тело функции
На имя функции в Python накладываются такие же ограничения, как и на прочие идентификаторы .
Соглашение рекомендует использовать:
- змеиный_регистр (англ. snake_case) для наименования функций: my_function ;
- пустые строки для отделения функций, а большие блоки кода помещать внутрь функций;
- строки документации .
В Python все данные — объекты, при вызове в функцию передается ссылка на этот объект. При этом, мутирующие объекты передаются по ссылке, немутирующие — по значению.
Функция в Python может возвращать результат своего выполнения, используя оператор return (например, return 5 ). В случае, если он не был указан или указан пустой оператор return , возвращается специальное значение None .
При встрече оператора return в коде Python немедленно завершает выполнение функции, аналогично break для циклических конструкций.
Пример определения и вызова функции приведен в Листинге 5.1.1 и на Рисунке 5.1.1.
Листинг 5.1.1 — Пример определения и вызова функции | скачать ¶
# Функция для вычисления гипотенузы # Имя: hypot, 2 параметра: x, y # return возвращает результат работы функции вызвавшему def hypot(x, y): return (x**2 + y**2)**0.5 z = hypot(3, 4) # Передача в функцию 2-х аргументов: 3 и 4 print(z) # 5.0 a = 5 b = 12 print(hypot(a, b)) # 13.0 - результат функции может быть использован сразу

Рисунок 5.1.1 — Передача параметров и возвращение результата функции ¶
Python, как и многие другие языки, позволяет создавать собственные (пользовательские) функции, среди которых можно выделить четыре типа (Листинг 5.1.2):
Доступны из любой точки программного кода в том же модуле или из других модулей.
Объявляются внутри других функций и видны только внутри них: используются для создания вспомогательных функций, которые нигде больше не используются.
Не имеют имени и объявляются в месте использования. В Python и представлены лямбда-выражениями.
Функции, ассоциированные с каким-либо объектом (например, list.append() , где append() — метод объекта list ).
Листинг 5.1.2 — Четыре типа функций в Python | скачать ¶
class Car: def move(self, x): # Метод (3) self.x += x def sum_of_cubes(x, y): # Глобальная функция (1) # Локальная функция (2) (ее "видит" только код внутри sum_of_cubes()) def cube(a): return a**3 return cube(x) + cube(y) # return возвращает результат выполнения тому, # кто вызвал эту функцию players = ["name": "Юрий", "rank": 5>, "name": "Сергей", "rank": 3>, "name": "Максим", "rank": 4>] # Анонимная функция (4) (лямбда-выражение) # В функции sorted() используется для определения порядка сортировки print(sorted(players, key=lambda player: player["name"])) # Сортировка по name # [, , ] print(sorted(players, key=lambda player: player["rank"])) # Сортировка по rank # [, , ]
5.1.3. Глобальные и локальные функции¶
5.1.3.1. Параметры и аргументы¶
5.1.3.1.1. Позиционные и ключевые параметры/аргументы¶
Все параметры, указываемые в Python при объявлении и вызове функции делятся на:
-
позиционные: указываются простым перечислением:
def function_name(a, b, c): # a, b, c - 3 позиционных параметра pass
def function_name(key=value, key2=value2): # key, key2 - 2 позиционных аргумента pass # value, value2 - их значения по умолчанию
Позиционные и ключевые аргументы могут быть скомбинированы. Синтаксис объявления и вызова функции зависит от типа параметра, однако позиционные параметры (и соответствующие аргументы) всегда идут перед ключевыми:
def example_func(a, b, c): # можно : 'a', 'b', 'c' - позиционные параметры pass def example_func(a, b, c=3): # можно : 'a', 'b' - позиционные параметры, pass # 'c' - ключевой параметр def example_func(a=1, b=2, c=3): # можно : 'a', 'b', 'c' - ключевые параметры pass def example_func(a=1, с, b=2): # нельзя: ключевой параметр 'a' pass # идет раньше позиционнных
def example_func(a, b, c=3): # a, b - позиционные параметры, c - ключевой параметр pass # Вызовы функции example_func(1, 2, 5) # можно : аргументы 1, 2, 5 распределяются # позиционно по параметрам 'a', 'b', 'c' example_func(1, 2) # можно : аргументы 1, 2 распределяются позиционно # по параметрам 'a', 'b' # в ключевой параметр 'c' аргумент # не передается, используется значение 3 example_func(a=1, b=2) # можно : аналогично example_func(1, 2), # все аргументы передаются по ключу example_func(b=2, a=1) # можно : аналогично example_func(a=1, b=2), # если все позиционные параметры заполнены как # ключевые аргументы, можно не соблюдать порядок example_func(c=5, b=2, a=1) # можно : аналогично example_func(1, 2), # аргументы передаются по ключу example_func(1) # нельзя: для позиционного аргумента 'b' # не передается аргумент example_func(b=1) # нельзя: для позиционного аргумента 'a' # не передается аргумент
Преимущества ключевых параметров:
- нет необходимости отслеживать порядок аргументов;
- у ключевых параметров есть значение по умолчанию, которое можно не передавать.
Пример функции со смешанными типами параметров приведен в Листинге 5.1.3.
Листинг 5.1.3 — Позиционные и ключевые параметры функций в Python | скачать ¶
# Функция выдает запрос и # - возвращает True в случае положительного ответа # - возвращает False в случае отрицательного ответа # - возвращает False если не получает ответ за [retries] попыток def ask_user(prompt, retries=3, hint="Ответьте, ДА или НЕТ?"): while True: retries -= 1 ok = input(prompt + " -> ").upper() if ok in ("Д", "ДА"): return True elif ok in ("Н", "НЕТ"): return False if retries 0: print("Не смог получить нужный ответ, считаю за отказ.") return False print(hint) # С ключевыми параметрами будут доступны также следующие варианты: # ask_user("Сохранить файл?", 0) # ask_user("Сохранить файл?", retries=1) # ask_user("Сохранить файл?", 2, "Жми Д или Н. ") # и др. if ask_user("Сохранить файл?"): print("Сохранил!") else: print("Не сохранил.") # ------------- # Пример вывода: # # Сохранить файл? -> Не знаю # Ответьте, ДА или НЕТ? # Сохранить файл? -> Да # Сохранил!
5.1.3.1.2. Упаковка и распаковка аргументов¶
В ряде случаев бывает полезно определить функцию, способную принимать любое число аргументов. Так, например, работает функция print() , которая может принимать на печать различное количество объектов и выводить их на экран.
Достичь такого поведения можно, используя механизм упаковки аргументов, указав при объявлении параметра в функции один из двух символов:
- * : все позиционные аргументы начиная с этой позиции и до конца будут собраны в кортеж;
- ** : все ключевые аргументы начиная с этой позиции и до конца будут собраны в словарь.
Пример упаковки аргументов приведен в Листинге 5.1.4.
Листинг 5.1.4 — Упаковка аргументов | скачать ¶
# При упаковке аргументов все переданные позиционные аргументы # будут собраны в кортеж 'order', а ключевые - в словарь 'info' def print_order(*order, **info): print("Музыкальная библиотека №1\n") # Словарь 'infos' должен содержать ключи 'author' и 'birthday' for key, value in sorted(info.items()): print(key, ":", value) # Кортеж 'order' содержит все наименования произведений print("Вы выбрали:") for item in order: print(" -", item) print("\nПриходите еще!") print_order("Славянский марш", "Лебединое озеро", "Спящая красавица", "Пиковая дама", "Щелкунчик", author="П.И. Чайковский", birthday="07/05/1840") # ------------- # Пример вывода: # # Музыкальная библиотека №1 # # author : П.И. Чайковский # birthday : 07/05/1840 # Вы выбрали: # - Славянский марш # - Лебединое озеро # - Спящая красавица # - Пиковая дама # - Щелкунчик # # Приходите еще!
Python также предусматривает и обратный механизм — распаковку аргументов, используя аналогичные обозначения перед аргументом:
- * : кортеж/список распаковывается как отдельные позиционные аргументы и передается в функцию;
- ** : словарь распаковывается как набор ключевых аргументов и передается в функцию.
Пример распаковки аргументов приведен в Листинге 5.1.5.
Листинг 5.1.5 — Распаковка аргументов | скачать ¶
# Площадь треугольника по формуле Герона # # Данный пример функции предназначен для демонстрации распаковки # Не проектируйте функцию таким образом - # расчетная функция должна возвращать число, а не строку! def heron_area_str(a, b, c, units="сантиметры", print_error=True): if a + b c or a + c b or b + c a: if print_error: return "Проверьте введенные стороны треугольника!" return p = (a + b + c) / 2 s = (p * (p - a) * (p - b) * (p - c)) ** 0.5 return "<> <>".format(s, units) abc = [3, 4, 5] params = dict(print_error=True, units="см.") # При распаковке аргументов список 'abc' будет распакован в # позиционные аргументы, а словарь 'params' - ключевые print(heron_area_str(*abc, **params)) # ------------- # Пример вывода: # # 6.0 см.
5.1.3.2. Область видимости¶
Область видимости — область программы, где определяются идентификаторы, и транслятор выполняет их поиск. За пределами области видимости тот же самый идентификатор может быть связан с другой переменной, либо быть свободным (не связанным ни с какой из них).
В Python выделяется четыре области видимости:
Собственная область внутри инструкции def .
Область в пределах вышестоящей инструкции def .
Область за пределами всех инструкций def — глобальная для всего модуля.
«Системная» область модуля builtins : содержит предопределенные идентификаторы, например, функцию max() и т.п.
Локальная и нелокальная области видимости являются относительными, глобальная и встроенная — абсолютными.
- идентификатор может называться локальным, глобальным и т.д., если имеет соответствующую область видимости;
- функции образуют локальную область видимости, а модули – глобальную;
- чем ближе область к концу списка, тем более она открыта (ее содержимое доступно для более закрытых областей видимости; например, глобальные идентификаторы и предопределенные имена могут быть доступны в локальной области видимости функции, но не наоборот).
В Листинге 5.1.6 приведен пример четырех областей видимости.
Листинг 5.1.6 — 4 области видимости в Python | скачать ¶
def min_of_cubes(x, y): # Идентификаторы 'x' и 'y' являются: # - локальными для min_of_cubes() # - нелокальными для cube() def cube(a): return a**3 # 'a' - локальный идентификатор функции cube() return min(cube(x), cube(y), cube(c)) # Функция min() находится # во встроенной области # видимости и видна везде # Идентификаторы 'a', 'b' и 'c' имеют глобальную область видимости a, b, c = 2, 3, 4 print(min_of_cubes(a, b)) # 8
Схема разрешения имен в языке Python называется правилом LEGB (Local, Enclosed, Global, Built-in) 6: когда внутри функции выполняется обращение к неизвестному имени, интерпретатор пытается отыскать его в четырех областях видимости по очереди до первого нахождения.
В Листингах 5.1.7 (а-д) приведены некоторые случае выполнения LEGB-правила.
Листинг 5.1.7 (а) — Области видимости в Python (пример) | скачать ¶
# Увеличиваем переменную 'a' локально def sum_of_2(a, b): a += 2 return a + b a, b = 3, 4 print(sum_of_2(a, b)) # 9 print(a, b) # 3 4
Листинг 5.1.7 (б) — Области видимости в Python (пример) | скачать ¶
# Добавляем к сумме локальную переменную 'x' def sum_of_2(a, b): x = 5 return a + b + x a, b = 3, 4 print(sum_of_2(a, b)) # 12 print(a, b, x) # NameError: name 'x' is not defined
Листинг 5.1.7 (в) — Области видимости в Python (пример) | скачать ¶
# Пробуем увеличить глобальную переменную 'c' def sum_of_2(a, b): c *= 5 # UnboundLocalError: local variable 'c' referenced before assignment return a + b + с a, b, c = 3, 4, 5 print(sum_of_2(a, b))
Листинг 5.1.7 (г) — Области видимости в Python (пример) | скачать ¶
# Пробуем изменить глобальную переменную 'c' def sum_of_2(a, b): с = 10 return a + b + с a, b, c = 3, 4, 5 print(sum_of_2(a, b)) # 17 print(a, b, c) # 3 4 5
Листинг 5.1.7 (д) — Области видимости в Python (пример) | скачать ¶
# Используем глобальную переменную 'c', не имея соответствующего параметра def sum_of_2(a, b): return a + b + c a, b, c = 3, 4, 5 print(sum_of_2(a, b)) # 12
По умолчанию, идентификаторы из другой области видимости доступны только для чтения, а, при попытке присвоения, функция создает локальный идентификатор.
Если необходимо изменять в функции переменные более закрытой области видимости, существует 3 способа:
- использовать инструкцию global : сообщая, что функция будет изменять один или более глобальных идентификаторов;
- использовать инструкцию nonlocal : сообщая, что вложенная функция будет изменять один или более идентификаторов внешних функций;
- передать мутирующий аргумент в качестве параметра функции.
В Листингах 5.1.8, 5.1.9 и 5.1.10 приведены примеры использования ключевых слов global , nonlocal , а также передачи мутирующего аргумента.
Листинг 5.1.8 — Использование global позволяет менять значение глобальной переменной внутри функции | скачать ¶
def func(): # 'value' создается как локальный идентификатор value = 100 def func_with_global(): global value # global указывает, что нужно использовать 'value' # из глобальной области видимости value = 100 value = 0 func() print(value) # 0 func_with_global() print(value) # 100
Листинг 5.1.9 — Использование nonlocal позволяет менять значение нелокальной переменной внутри вложенной функции | скачать ¶
def func(): def inner_func(): # 'value' создается как локальный идентификатор inner_func() value = 100 def inner_func_with_nonlocal(): nonlocal value # Благодаря nonlocal используется 'value' из func() value = 100 value = 10 inner_func() print(value) # 10 inner_func_with_nonlocal() print(value) # 100 value = 0 func() print("global value =", value) # 0
Листинг 5.1.10 — Передача мутирующего аргумента в функцию | скачать ¶
# Функция принимает список, и добавляет сумму элементов в конец списка # # Изменение внутри функции мутирующего объекта приводит к его # изменению и в вызывающем коде def sum_list(lst): lst.append(sum(lst)) my_list = [1, 2, 3, 4, 5] sum_list(my_list) print(my_list) # [1, 2, 3, 4, 5, 15]
К изменению переменных из другой области видимости необходимо относиться крайне осторожно и прибегать только в случае крайней необходимости.
В большинстве случаев необходимо придерживаться концепции изолированного доступа через области видимости.
В связи с тем, что мутирующие аргументы могут быть изменены внутри функции, стоит аккуратно использовать их в качестве значений ключевых аргументов по умолчанию, которые создаются при инициализации функции (Листинг 5.1.11).
Листинг 5.1.11 — Мутирующие аргументы сохраняют значения после нескольких вызовов | скачать ¶
# Функция принимает число и список, к которому его нужно добавить # Если список не передан, число должно оказаться в пустом списке # 1. Данная реализация не учитывает единовременное создание значений # ключевых аргументов, и приводит к неожиданным эффектам def change_list(a, lst=[]): lst.append(a) return lst my_list = change_list(1) my_list = change_list(2) my_list = change_list(3) print(my_list) # [1, 2, 3] # Та же функция, реализованная правильно def change_list_2(a, lst=None): L = lst if L is None: L = [] L.append(a) return L my_list = change_list_2(1) my_list = change_list_2(2) my_list = change_list_2(3) print(my_list) # [3]
5.1.3.3. Возврат нескольких значений¶
Часто из функции необходимо вернуть несколько значений (например, в Паскале, для этого используются выходные параметры с ключевым словом var ). Одним из лучших способов для этого в Python является возврат кортежа с несколькими значениями (Листинг 5.1.12).
Листинг 5.1.12 — Возврат нескольких значений в виде кортежа | скачать ¶
# Функция выполняет решение квадратного уравнения, # сообщая вызывающему коду, сколько решений удалось получить # в формате (num, (x1, . )), # где в начале идет количество решений, а в отдельном кортеже сами решения def solve_equation(a, b, c): d = b**2 - 4 * a * c if d 0: return (0, ()) elif d == 0: x = -b / (2*a) return (1, (x, )) else: x1 = (-b - d**0.5) / (2*a) x2 = (-b + d**0.5) / (2*a) return (2, (x1, x2)) # Рекурсивный вариант вычисления факториала a = int(input("a = ")) b = int(input("b = ")) c = int(input("c = ")) num, x = solve_equation(a, b, c) print("\nРезультат решения: ", end="") if num == 0: print("решений нет") elif num == 1: print("x =", x[0]) elif num == 2: print("x1 =", x[0], " x2 =", x[1]) else: print("ошибка!") # ------------- # Пример вывода: # a = 1 # b = 4 # c = 3 # # Результат решения: x1 = -3.0 x2 = -1.0
Прочие способы (например, изменение глобальных переменных) не рекомендуются 7.
5.1.3.4. Рекурсия¶
Рекурсия — вызов функции внутри самой себя, непосредственно (простая рекурсия) или через другие функции (сложная или косвенная рекурсия)
Количество вложенных вызовов функции или процедуры называется глубиной рекурсии. Рекурсивная программа позволяет описать повторяющееся или даже потенциально бесконечное вычисление, причем без явных повторений частей программы и использования циклов.
Не рекомендуется использовать рекурсию, если такая функция может привести или приводит к большой глубине рекурсии — лучше заменить ее циклической конструкцией. Рекурсивный вызов требуется некоторое количество оперативной памяти компьютера, и при чрезмерно большой глубине рекурсии может наступить переполнение стека (англ. англ. Stack Overflow) вызовов.
В Листинге 5.1.13 приведен пример реализации рекурсивной функции.
Листинг 5.1.13 — Рекурсивные функции | скачать ¶
# Вычисление факториала, используя цикл def factorial_1(x): res = 1 for i in range(x): res *= i + 1 return res # Рекурсивный вариант вычисления факториала def factorial_2(x): if x == 1: return 1 else: return x * factorial_2(x - 1) print(factorial_1(5)) # 120 print(factorial_2(5)) # 120
5.1.3.5. Строки документации¶
Документирование кода — важный аспект, от которого зависит читаемость и быстрота понимания кода всеми участниками команды разработки.
Python предоставляет возможность добавить документацию (описание) к любой функции, используя строки документирования — это обычные строки тройных кавычках «»» , которые следуют сразу за строкой с инструкцией def перед программным кодом функции и воспринимаются транслятором специальным образом.
Соглашения по документированию функций содержатся в документе PEP 257.
Верно оформленная строка документации является краткой справкой по функции, которую можно увидеть, вызвав метод __doc__ , или функцию help() .
В Листинге 5.1.14 приведен пример написания документации к функции.
Листинг 5.1.14 — Документирование функции в Python | скачать ¶
# Для небольшой функции можно использовать однострочное документирование # Как правило, это описание действия в повелительном наклонении def sqrt(x): """Вернуть квадратный корень из 'x'.""" return x**0.5 # Если функция объемная, используется многострочное документирование def heron(a, b, c): """Вернуть площадь треугольника по формуле Герона. Параметры: - a, b, c (float): стороны треугольника. Результат: - float: значение площади. - None: если треугольник не существует. """ if not (a + b > c and a + c > b and b + c > a): return p = (a + b + c) / 2 return sqrt(p * (p - a) * (p - b) * (p - c)) # Справочную информацию о функции можно получить 2 способами: # heron.__doc__ или help(heron) print(heron.__doc__) params = [float(x) for x in input('Введите стороны (a b c): ').split()] s = heron(*params) if s: print('S = '.format(s)) else: print('Треугольник не существует!') # ------------- # Пример вывода: # Вернуть площадь треугольника по формуле Герона. # # Аргументы: # - a, b, c (float): стороны треугольника. # # Результат: # - float: значение площади. # - None: если треугольник не существует. # # Введите стороны (a b c): 3 4 5 # S = 6.00
5.1.4. Анонимные функции¶
Python поддерживает синтаксис, позволяющий определять анонимные функции (лямбда-функции или лямбда-выражения):
lambda parameters: expression
- часть parameters является необязательной, и если она присутствует, то обычно представляет собой простой список имен переменных, разделенных запятыми (позиционных аргументов);
- выражение expression не может содержать условных инструкций или циклов (условные выражения — допустимы), а также не может содержать инструкцию return ;
- результатом лямбда-выражения является анонимная функция.
Когда лямбда-функция вызывается, она возвращает результат вычисления выражения expression .
Пример записи лямбда-функции приведен в Листинге 5.1.15.
Листинг 5.1.15 — Лямбда-функции | скачать ¶
# Лямбда-функции, как правило, используются в случаях, где использование # функции не требует наличия у нее имени # # Если это требуется - лучше объявить обычную функцию, используя def # 1. Обычная и лямбда-функция выполняют одно и то же действие, # разница в синтаксисе def sqr1(x): return x**2 sqr2 = lambda x: x**2 # Если лямбда-выражение привязывается к идентификатору - # - оно не нужно; используйте обычные функции print(sqr1(6)) # 36 print(sqr2(6)) # 36 # 2. Лямбда-выражения удобно использовать для элементов функционального программирования # Эл-ты из таблицы Менделеева (номер группы, порядковый номер, наименование) elements = [(2, 12, "Mg"), (1, 11, "Na"), (1, 3, "Li"), (2, 4, "Be")] elements.sort(key=lambda x: x[1]) # Сортировка порядковому номеру print(elements) # [(1, 3, 'Li'), (2, 4, 'Be'), (1, 11, 'Na'), (2, 12, 'Mg')] # Функции max и min имеют ключевой аргумент key - параметр сортировки # key - ссылка на функцию, имеющую 1 возвращающую значение, по которому следует # сравнивать величины # 2.1. Используя лямбда-выражение lst = ["Java", "Algol", "C++"] print(max(lst, key=lambda x: x.count("a"))) # Элемент lst, в котором # больше всего "a" # 2.2. Тоже самое возможно с использованием обычной функции def find_a(x): return x.find("a") print(min(lst, key=find_a)) # Элемент lst, в котором # "a" находится левее
5.1.5. Побочный эффект¶
Побочный эффект (англ. Side Effect) — любые действия программы, изменяющие среду выполнения (англ. Execution Environment).
К побочным эффектам выполнения функции можно отнести:
- изменение данных в памяти;
- чтение/запись файла или устройства;
- ввод/вывод значений;
- самостоятельную реакцию на исключительные ситуации;
- и др.
Часто функции с побочным эффектом при вызове несколько раз с одними и теми же аргументами в качестве результата возвращают разные значения. Пример — стандартная функция генерации случайного числа.
Создавая функцию, необходимо избегать побочных эффектов — такие функции легче тестируются и не содержат скрытых действий. Один из примеров такой функции — функция solve_equation() в Листинге 5.1.12 .
Естественно, что полностью избежать побочных эффектов невозможно. В таких случаях необходимо локализовать участки кода с побочным эффектом в отдельные функции (Листинге 5.1.16).
Листинг 5.1.16 — Локализация кода с побочным эффектом в отдельные функции | скачать ¶
def heron(a, b, c): """Вернуть площадь треугольника по формуле Герона. Параметры: - a, b, c (float): стороны треугольника. Результат: - float: значение площади. - None: если треугольник не существует. """ if not (a + b > c and a + c > b and b + c > a): return p = (a + b + c) / 2 return (p * (p - a) * (p - b) * (p - c))**0.5 def input_data(): """Запросить стороны треугольника с клавиатуры. Результат: - tuple of float: (a, b, c). Побочный эффект! """ return (float(x) for x in input('Введите стороны (a b c): ').split()) def print_res(res): """Вывести на экран 'res'. Параметры: - res (float): площадь треугольника. Побочный эффект! """ if res: print('S = '.format(res)) else: print('Треугольник не существует!') a, b, c = input_data() res = heron(a, b, c) print_res(res)
Решая задачу, необходимо следить чтобы каждая проектируемая функция выполняла минимальную, логически полную задачу.
Например, если необходимо вычислить сумму и среднее значение элементов списка, правильнее будет создать 2 функции для каждого вычисления, а не одну; при этом ввод и вывод значений также оформить в виде отдельных функций.
Sebesta, W.S Concepts of Programming languages. 10E; ISBN 978-0133943023.
Саммерфилд М. Программирование на Python 3. Подробное руководство. — М.: Символ-Плюс, 2009. — 608 с.: ISBN: 978-5-93286-161-5.
Лучано Рамальо. Python. К вершинам мастерства. — М.: ДМК Пресс , 2016. — 768 с.: ISBN: 978-5-97060-384-0, 978-1-491-94600-8.
A Beginner’s Guide to Python’s Namespaces, Scope Resolution, and the LEGB Rule. URL: http://sebastianraschka.com/Articles/2014_python_scope_and_namespaces.html.
How do I write a function with output parameters (call by reference). URL: https://docs.python.org/3/faq/programming.html#id17.
Версия: 2023. Обновлено: 16.05.2023.
Встроенные функции Python: какие нужно знать и на какие не стоит тратить время
В статье расскажем про стандартные встроенные функции Python: какие используются часто, а какие вам, вероятно, не пригодятся никогда.
В Python существуют десятки встроенных функций и классов, сотни инструментов, входящих в стандартную библиотеку Python, и тысячи сторонних библиотек на PyPI. Держать всё в голове начинающему программисту нереально. В статье расскажем про стандартные встроенные функции Python: какие используются часто, а какие вам, вероятно, не пригодятся никогда.
Чтобы разобраться, на какие функции стоит обратить внимание, их следует разделить на группы:
- общеизвестные: почти все новички используют эти функции и довольно часто;
- неочевидные для новичков: об этих функциях полезно знать, но их легко пропустить, когда вы новичок в Python;
- понадобятся позже: об этих встроенных функциях полезно помнить, чтобы найти их потом, когда/если они понадобятся;
- можно изучить когда-нибудь: это может пригодиться, но только при определённых обстоятельствах;
- скорее всего, они вам не нужны: они вряд ли понадобятся, если вы не занимаетесь чем-то достаточно специализированным.
Встроенные функции в первых двух категориях являются основными. Они в конечном итоге будут нужны почти всем начинающим программистам на Python. Встроенные модули в следующих двух категориях являются специализированными, но потребности в них будут варьироваться в зависимости от вашей специализации. Категория 5 — это скрытые встроенные функции. Они очень полезны, когда в них есть необходимость, но многим программистам Python они, вероятно, никогда не понадобятся.
Общеизвестные функции
Если вы уже писали код на Python, эти модули должны быть вам знакомы.
Вряд ли найдётся разработчик, даже начинающий, который не знает эту функцию вывода. Как минимум реализация «Hello, World!» требует использования данного метода. Но вы можете не знать о различных аргументах, которые можно передавать в print .
>>> words = ["Welcome", "to", "Python"] >>> print(words) ['Welcome', 'to', 'Python'] >>> print(*words, end="!\n") Welcome to Python! >>> print(*words, sep="\n") Welcome to Python
len
В Python нет синтаксиса вроде my_list.length() или my_string.length , вместо этого используются поначалу непривычные конструкции len(my_list) и len(my_string) .
>>> words = ["Welcome", "to", "Python"] >>> len(words) 3
Нравится вам такая реализация или нет, другой альтернативы не предусмотрено, поэтому к ней нужно привыкнуть.
str
К сожалению, в отличие от многих других языков программирования, в Python нельзя объединять строки и числа.
>>> version = 3 >>> "Python " + version Traceback (most recent call last): File "", line 1, in TypeError: can only concatenate str (not "int") to str
Python отказывается приводить целое число 3 к типу строка, поэтому нужно сделать это самостоятельно, используя встроенную функцию str (технически это класс, но с целью уменьшить количество ненужной информации будем принимать все методы за функции).
>>> version = 3 >>> "Python " + str(version) 'Python 3'
int
Если нужно пользовательский ввод преобразовать в integer , эта функция незаменима. Она может преобразовывать строки в целые числа.
>>> program_name = "Python 3" >>> version_number = program_name.split()[-1] >>> int(version_number) 3
Эту функцию также можно использовать для отсечения дробной части у числа с плавающей точкой.
>>> from math import sqrt >>> sqrt(28) 5.291502622129181 >>> int(sqrt(28)) 5
Обратите внимание, если нужно обрезать дробную часть при делении, оператор « // » более уместен (с отрицательными числами это работает иначе).
int (3/2) == 3 // 2
float
Если строка, которую надо конвертировать в число, не является целым числом, здесь поможет метод float .
>>> program_name = "Python 3" >>> version_number = program_name.split()[-1] >>> float(version_number) 3.0 >>> pi_digits = '3.141592653589793238462643383279502884197169399375' >>> len(pi_digits) 50 >>> float(pi_digits) 3.141592653589793
Float также можно использовать для преобразования целых чисел в числа с плавающей запятой.
В Python 2 такое преобразование необходимо, но в Python 3 целочисленное деление больше не является чем-то особенным (если вы специально не используете оператор « // »). Поэтому больше не нужно использовать float для этой цели, теперь float(x)/y можно легко заменить на x/y .
list
Эта функция может очень облегчить задачу, если вы хотите составить список из итераций цикла.
>>> numbers = [2, 1, 3, 5, 8] >>> squares = (n**2 for n in numbers) >>> squares at 0x7fd52dbd5930> >>> list_of_squares = list(squares) >>> list_of_squares [4, 1, 9, 25, 64]
При работе со списком метод copy позволяет создать его копию.
>>> copy_of_squares = list_of_squares.copy()
Если вы не знаете, с какими элементами работаете, функция list является более общим способом перебора элементов и их копирования.
>>> copy_of_squares = list(list_of_squares)
Также можно использовать списковое включение, но делать это не рекомендуется.
Обратите внимание, когда вы хотите создать пустой список, следует использовать буквальный синтаксис списка (« [ ] »).
>>> my_list = list() # Так делать нельзя >>> my_list = [] # Так можно
Использование « [ ] » считается более идиоматическим, так как эти скобки на самом деле выглядят как список Python.
tuple
Эта функция во многом похожа на функцию list , за исключением того, что вместо списков она создает кортежи.
>>> numbers = [2, 1, 3, 4, 7] >>> tuple(numbers) (2, 1, 3, 4, 7)
Если вы пытаетесь создать хешируемую коллекцию (например, ключ словаря), стоит отдать предпочтению кортежу вместо списка.
dict
Эта функция создаёт новый словарь.
Подобно спискам и кортежам, dict эквивалентна проходу по массиву пар «ключ-значение» и созданию из них словаря.
Дан список кортежей, по два элемента в каждом.
>>> color_counts = [('red', 2), ('green', 1), ('blue', 3), ('purple', 5)]
Выведем его на экран с помощью цикла.
>>> colors = <> >>> for color, n in color_counts: . colors[color] = n . >>> colors
То же самое, но с использованием dict .
>>> colors = dict(color_counts) >>> colors
Функция dict может принимать 2 типа аргументов:
- другой словарь: в этом случае этот словарь будет скопирован;
- список кортежей «ключ-значение»: в этом случае из этих слов будет создан новый словарь.
Поэтому следующий код также будет работать.
>>> colors >>> new_dictionary = dict(colors) >>> new_dictionary
Функция dict также может принимать ключевые слова в качестве аргументов для создания словаря со строковыми ключами.
>>> person = dict(name='Trey Hunner', profession='Python Trainer') >>> person
Но рекомендуется всё же использовать литералы вместо ключевых слов.
>>> person = >>> person
Такой синтаксис более гибок и немного быстрее. Но самое главное он более чётко передаёт факт того, что вы создаёте именно словарь.
Как в случае со списком и кортежем, пустой словарь следует создавать с использованием буквального синтаксиса (« < >»).
>>> my_list = dict() # Так делать нельзя >>> my_list = <> # Так можно
Использование « < >» более идиоматично и эффективно с точки зрения использования процессора. Обычно для создания словарей используются фигурные скобки, dict встречается гораздо реже.
set
Функция set создаёт новый набор. Она принимает итерации из хешируемых значений (строк, чисел или других неизменяемых типов) и возвращает set .
>>> numbers = [1, 1, 2, 3, 5, 8] >>> set(numbers)
Создать пустой набор с « < >» нельзя (фигурные скобки создают пустой словарь). Поэтому функция set — лучший способ создать пустой набор.
>>> numbers = set() >>> numbers set()
Можно использовать и другой синтаксис.
>>> # Так можно создать пустой набор set()
Такой способ имеет недостаток — он сбивает с толку (он основан на редко используемой функции оператора * ), поэтому он не рекомендуется.
range
Эта функция создаёт объект range , который представляет собой диапазон чисел.
>>> range(10_000) range(0, 10000) >>> range(-1_000_000_000, 1_000_000_000) range(-1000000000, 1000000000)
Результирующий диапазон чисел включает начальный номер, но исключает конечный ( range(0, 10) не включает 10).
Данная функция полезна при переборе чисел.
>>> for n in range(0, 50, 10): . print(n) . 0 10 20 30 40
Обычный вариант использования — выполнить операцию n раз.
first_five = [get_things() for _ in range(5)]
Функция range в Python 2 возвращает список. Это означает, что примеры кода выше будут создавать очень большие списки. Range в Python 3 работает как xrange в Python 2. Числа вычисляются «более лениво» при проходе по диапазону.
Функции, неочевидные для новичков
bool
Эта функция проверяет достоверность (истинность) объектов Python. Относительно чисел будет выполняться проверка на неравенство нулю.
>>> bool(5) True >>> bool(-1) True >>> bool(0) False
Применяя bool к коллекциям, будет проверяться их длина (больше 0 или нет).
>>> bool('hello') True >>> bool('') False >>> bool(['a']) True >>> bool([]) False >>> bool(<>) False >>> bool() True >>> bool(range(5)) True >>> bool(range(0)) False >>> bool(None) False
Проверка истинности очень важна в Python. Вместо того, чтобы задавать вопросы о длине контейнера, многие новички задают проверку истинности.
# Вместо этого if len(numbers) == 0: print("The numbers list is empty") # многие делают так if not numbers: print("The numbers list is empty")
Данная функция используется редко. Но, если нужно привести значение к логическому типу для проверки его истинности, bool вам необходима.
enumerate
Если нужно в цикле посчитать количество элементов (по одному элементу за раз), эта функция может быть очень полезной. Такая задача может показаться специфической, но она бывает нужна довольно часто.
Например, если нужно отслеживать номер строки в файле.
>>> with open('hello.txt', mode='rt') as my_file: . for n, line in enumerate(my_file, start=1): . print(f"", line) . 001 This is the first line of the file 002 This is the second line 003 This is the last line of the file
Enumerate также часто используется для отслеживания индекса элементов в последовательности.
def palindromic(sequence): """Возвращает True, если последовательность является палиндромом.""" for i, item in enumerate(sequence): if item != sequence[-(i+1)]: return False return True
Также следует обратить внимание, что новички в Python часто используют range(len(sequence)) . Если вы когда-нибудь встретите конструкции типа range(len(. )) , лучше заменить её на enumerate . Она поможет упростить конструкцию операторов.
def palindromic(sequence): """Возвращает True, если последовательность является палиндромом.""" for i in range(len(sequence)): if sequence[i] != sequence[-(i+1)]: return False return True
zip
Эта функция ещё более специализирована, чем enumerate . Zip используется для перебора сразу нескольких объектов одновременно.
>>> one_iterable = [2, 1, 3, 4, 7, 11] >>> another_iterable = ['P', 'y', 't', 'h', 'o', 'n'] >>> for n, letter in zip(one_iterable, another_iterable): . print(letter, n) . P 2 y 1 t 3 h 4 o 7 n 11
По сравнению с enumerate , последняя функция удобна, когда нужна индексация во время цикла. Если нужно обрабатывать несколько объектов одновременно, zip предпочтительнее enumerate .
reversed
Функция reversed , как enumerate и zip , возвращает итератор.
>>> numbers = [2, 1, 3, 4, 7] >>> reversed(numbers)
Единственное, что можно сделать с этим итератором, пройтись по нему (но только один раз).
>>> reversed_numbers = reversed(numbers) >>> list(reversed_numbers) [7, 4, 3, 1, 2] >>> list(reversed_numbers) []
Подобно enumerate и zip , reversed является своего рода вспомогательной функцией в циклах. Её использование можно увидеть исключительно в цикле for .
>>> for n in reversed(numbers): . print(n) . 7 4 3 1 2
Есть несколько и других способов перевернуть списки в Python.
# Синтаксис нарезки for n in numbers[::-1]: print(n) # Метод переворота на месте numbers.reverse() for n in numbers: print(n)
Данная функция, как правило, является лучшим способом «перевернуть» любой список (а также набор, массив и т. д.) в Python.
В отличие от numbers.reverse() , reversed не изменяет список, а возвращает итератор перевёрнутых элементов.
reversed(numbers) (в отличие от numbers [:: — 1] ) не создает новый список. Возвращаемый им итератор извлекает следующий элемент в обратном порядке при проходе по циклу. Также синтаксис reversed(numbers) намного более читабелен, чем numbers [:: — 1] .
Можно использовать факт, что reversed не копирует список. Если объединить его с функцией zip , можно переписать функцию palindromic (из раздела enumerate ), не занимая дополнительной памяти (не копируя объект).
def palindromic(sequence): """Возвращает True, если последовательность является палиндромом.""" for n, m in zip(sequence, reversed(sequence)): if n != m: return False return True
sum
Эта функция берёт набор чисел и возвращает их сумму.
>>> sum([2, 1, 3, 4, 7]) 17
В Python есть много вспомогательных функций, которые выполняют циклы за вас (отчасти потому, что они хорошо сочетаются с генератор-выражениями).
>>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> sum(n**2 for n in numbers) 524
min и max
Эти функции выдают минимальное и максимальное число из набора соответственно.
>>> numbers = [2, 1, 3, 4, 7, 11, 18] >>> min(numbers) 1 >>> max(numbers) 18
Min и max также принимают key -свойство, позволяющее настроить, что на самом деле означают «минимум» и «максимум» для конкретных объектов.
>>> fruits = ['kumquat', 'Cherimoya', 'Loquat', 'longan', 'jujube'] >>> sorted(fruits, key=len) ['Loquat', 'longan', 'jujube', 'kumquat', 'Cherimoya']
sorted
Эта функция принимает любой набор элементов и возвращает новый список всех значений в отсортированном порядке.
>>> numbers = [1, 8, 2, 13, 5, 3, 1] >>> words = ["python", "is", "lovely"] >>> sorted(words) ['is', 'lovely', 'python'] >>> sorted(numbers, reverse=True) [13, 8, 5, 3, 2, 1, 1]
Данная функция (как min и max ) сравнивает элементы, используя оператор < , поэтому все значения, переданные ей, должны быть упорядочены.
Sorted также позволяет настраивать сортировку с помощью key -свойства.
any и all
Эти функции могут быть использованы в паре с генератор-выражениями, чтобы определить соответствие элементов заданному условию.
Используя all , можно переписать функцию palindromic следующим образом.
def palindromic(sequence): """Возвращает True, если последовательность является палиндромом.""" return all( n == m for n, m in zip(sequence, reversed(sequence)) )
Отрицание условия и возвращаемого значения позволит также использовать any в этом примере точно также (что усложнит конструкцию, но вполне сойдёт в качестве примера использования).
def palindromic(sequence): """Возвращает True, если последовательность является палиндромом.""" return not any( n != m for n, m in zip(sequence, reversed(sequence)) )
5 функций для отладки
Эти функции часто игнорируются, но будут полезны для отладки и устранения неисправностей кода.
breakpoint
Если нужно приостановить выполнение кода и перейти в командную строку Python, эта функция вам пригодится. Вызов breakpoint перебросит вас в отладчик Python.
Эта встроенная функция была добавлена в Python 3.7, но если вы работаете в более старых версиях, можете получить тот же результат с помощью import pdb; pdb.set_trace() .
dir
Эта функция может использоваться в двух случаях:
- просмотр списка всех локальных переменных;
- просмотр списка всех атрибутов конкретного объекта.
Из примера можно увидеть локальные переменные сразу после запуска и после создания новой переменной x .
>>> dir() ['__annotations__', '__doc__', '__name__', '__package__'] >>> x = [1, 2, 3, 4] >>> dir() ['__annotations__', '__doc__', '__name__', '__package__', 'x']
Если в dir передать созданный список x , на выходе можно увидеть все его атрибуты.
>>> dir(x) ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
В выведенном списке атрибутов можно увидеть его типичные методы ( append , pop , remove и т. д.) , а также множество более сложных методов для перегрузки операторов.
vars
Эта функция является своего рода смесью двух похожих инструментов: locals() и __dict__ .
Когда vars вызывается без аргументов, это эквивалентно вызову locals() , которая показывает словарь всех локальных переменных и их значений.
>>> vars() , '__spec__': None, '__annotations__': <>, '__builtins__': >
Когда вызов происходит с аргументом, vars получает доступ к атрибуту __dict__ , который представляет собой словарь всех атрибутов экземпляра.
>>> from itertools import chain >>> vars(chain) mappingproxy(, '__iter__': , '__next__': , '__new__': , 'from_iterable': , '__reduce__': , '__setstate__': , '__doc__': 'chain(*iterables) --> chain object\n\nReturn a chain object whose .__next__() method returns elements from the\nfirst iterable until it is exhausted, then elements from the next\niterable, until all of the iterables are exhausted.'>)
Перед использованием vars было бы неплохо сначала обратиться к dir .
type
Эта функция возвращает тип объекта, который вы ей передаете.
Тип экземпляра класса есть сам класс.
>>> x = [1, 2, 3] >>> type(x)
Тип класса — это его метакласс, обычно это type .
>>> type(list) >>> type(type(x))
Атрибут __class__ даёт тот же результат, что и функция type , но рекомендуется использовать второй вариант.
>>> x.__class__ >>> type(x)
Функция type , кроме отладки, иногда полезна и в реальном коде (особенно в объектно-ориентированном программировании с наследованием и пользовательскими строковыми представлениями).
Обратите внимание, что при проверке типов обычно вместо type используется функция isinstance . Также стоит понимать, что в Python обычно не принято проверять типы объектов (вместо этого практикуется утиная типизация).
help
Если вы находитесь в Python Shell или делаете отладку кода с использованием breakpoint , и хотите знать, как работает определённый объект, метод или атрибут, функция help поможет вам.
В действительности вы, скорее всего, будете обращаться за помощью к поисковой системе. Но если вы уже находитесь в Python Shell, вызов help(list.insert) будет быстрее, чем поиск документации в Google.
Функции, которые пригодятся позже
В начале изучения Python эти функции вам по большей части будут не нужны, но в конечном итоге они вам понадобятся.
open
Эта функция служит для открытия файла и последующей работы с ним. Но, если вы не работаете с файлами напрямую, то она вам может и не пригодиться.
Несмотря на то, что работа с файлами очень распространена, далеко не все программисты Python работают с файлами через open . Например, разработчики Django могут не использовать её вообще.
input
Эта функция запрашивает у пользователя ввод, ждёт нажатия клавиши Enter, а затем возвращает набранный текст.
Чтение из стандартного ввода — это один из способов получить входные данные в программе. Но есть и много других способов: аргументы командной строки, чтение из файла, чтение из базы данных и многое другое.
repr
Эта функция необходима для представления объекта в читабельном виде.
Для многих объектов функции str и repr работают одинаково.
>>> str(4), repr(4) ('4', '4') >>> str([]), repr([]) ('[]', '[]')
Но есть объекты, для которых их применение различается.
>>> str('hello'), repr("hello") ('hello', "'hello'") >>> from datetime import date >>> str(date(2020, 1, 1)), repr(date(2020, 1, 1)) ('2020-01-01', 'datetime.date(2020, 1, 1)')
Строковое представление, которое вы видите в Python Shell, использует repr , тогда как функция print использует str .
>>> date(2020, 1, 1) datetime.date(2020, 1, 1) >>> "hello!" 'hello!' >>> print(date(2020, 1, 1)) 2020-01-01 >>> print("hello!") hello!
Также repr используется при ведении лог-журнала, обработке исключений и реализации более сложных методов.
super
Эта функция очень важна, если используется наследование одного класса от другого.
Многие пользователи Python редко создают классы. Они не являются важной частью Python, хоть для многих типов программирования они необходимы. Например, вы не можете использовать веб-фреймворк Django без создания классов.
property
Декоратор позволяет создать атрибут, который всегда будет содержать возвращаемое значение конкретного вызова функции. Это проще всего понять на примере.
Пример класса, который использует property .
class Circle: def __init__(self, radius=1): self.radius = radius @property def diameter(self): return self.radius * 2
Здесь вы можете увидеть доступ к атрибуту diameter объекта Circle .
>>> circle = Circle() >>> circle.diameter 2 >>> circle.radius = 5 >>> circle.diameter 10
Если вы занимаетесь объектно-ориентированным программированием на Python, вам, вероятно, захочется узнать о property больше в какой-то момент. В отличие от других объектно-ориентированных языков, в Python property используется вместо методов getter и setter .
issubclass и isinstance
Функция issubclass проверяет, является ли класс подклассом одного или нескольких других классов.
>>> issubclass(int, bool) False >>> issubclass(bool, int) True >>> issubclass(bool, object) True
Функция isinstance проверяет, является ли объект экземпляром одного или нескольких классов.
>>> isinstance(True, str) False >>> isinstance(True, bool) True >>> isinstance(True, int) True >>> isinstance(True, object) True
Функция isinstance может быть представлена как делегирование в issubclass .
>>> issubclass(type(True), str) False >>> issubclass(type(True), bool) True >>> issubclass(type(True), int) True >>> issubclass(type(True), object) True
Если вы перегружаете операторы, вам может понадобиться использование isinstance , но в целом в Python стараются избегать строгой проверки типов, поэтому особой нужды в данных функциях нет.
hasattr, getattr, setattr и delattr
Если нужно работать с атрибутами объекта, но имя атрибутов является динамическим и постоянно меняется, данные функции вам будут необходимы.
Например, есть объект thing , который нужно проверить на конкретное значение.
>>> class Thing: pass . >>> thing = Thing()
Функция hasattr позволяет проверить, имеет ли объект определённый атрибут.
>>> hasattr(thing, 'x') False >>> thing.x = 4 >>> hasattr(thing, 'x') True
Функция getattr позволяет получить значение атрибута (с необязательным значением по умолчанию, если атрибут не существует).
>>> getattr(thing, 'x') 4 >>> getattr(thing, 'x', 0) 4 >>> getattr(thing, 'y', 0) 0
Функция setattr позволяет установить значение атрибута.
>>> setattr(thing, 'x', 5) >>> thing.x 5
И delattr соответственно удаляет атрибут.
>>> delattr(thing, 'x') >>> thing.x Traceback (most recent call last): File "", line 1, in AttributeError: 'Thing' object has no attribute 'x'
classmethod и staticmethod
Если у вас есть метод, который должен вызываться в экземпляре или в классе, вам нужен декоратор classmethod . Фабричные методы (альтернативные конструкторы) являются распространённым случаем для этого.
class RomanNumeral: """Римская цифра, представленная как строка и число.""" def __init__(self, number): self.value = number @classmethod def from_string(cls, string): return cls(roman_to_int(string)) # Функция пока еще не существует
Немного сложнее придумать хорошее использование staticmethod , так как всегда можно использовать функцию уровня модуля вместо статического метода.
class RomanNumeral: """Римская цифра, представленная как строка и число.""" SYMBOLS = def __init__(self, number): self.value = number @classmethod def from_string(cls, string): return cls(cls.roman_to_int(string)) @staticmethod def roman_to_int(numeral): total = 0 for symbol, next_symbol in zip_longest(numeral, numeral[1:]): value = RomanNumeral.SYMBOLS[symbol] next_value = RomanNumeral.SYMBOLS.get(next_symbol, 0) if value < next_value: value = -value total += value return total
Функция roman_to_int не требует доступа к экземпляру или классу, поэтому ей не нужно быть @classmethod . Фактически нет необходимости делать эту функцию staticmethod (вместо classmethod ). staticmethod является просто более сдерживающим, чтобы сигнализировать о том факте, что функция не зависима от класса, в котором она находится.
next
Данная функция возвращает следующий элемент в итераторе.
Она может работать со следующими видами итераторов:
- объекты enumerate ;
- объекты zip ;
- возвращаемые значения функции reversed ;
- файлы
- объекты csv.reader ;
- генератор-выражения;
- генератор-функции;
Функция next может быть представлена как способ вручную перебрать набор, чтобы получить один единственный элемент, а затем выйти из перебора.
Функции, которые когда-нибудь можно выучить
Следующие встроенные функции Python определённо не бесполезны, но они более специализированы.
Эти функции вам, возможно, будут нужны, но также есть шанс, что вы никогда не прибегнете к ним в своём коде.
- iter: возвращает итератор (список, набор и т. д.);
- callable: возвращает True , если аргумент является вызываемым;
- filter and map: вместо них рекомендуется использовать генератор-выражения;
- Round: округляет число;
- divmod: эта функция выполняет деление без остатка ( // ) и операцию по модулю ( % ) одновременно;
- bin, oct и hex: служат для отображения чисел в виде строки в двоичной, восьмеричной или шестнадцатеричной форме;
- abs: возвращает абсолютное значение числа (аргумент может быть целым или числом с плавающей запятой, если аргумент является комплексным числом, его величина возвращается);
- hash;
- object.
Прочие специфические функции
- ord и chr: могут пригодиться при изучении ASCII или Unicode;
- exec и eval: для исполнения строки;
- compile;
- slice: если вы реализуете __getitem__ для создания пользовательской последовательности, это может вам понадобиться;
- bytes, bytearray и memoryview: если вы часто работаете с байтами;
- ascii: похож на repr , но возвращает представление объекта только в ASCII;
- frozenset: как set , но он неизменен (и хешируемый);
- __import__: лучше использовать importlib ;
- format: вызывает метод __format__ , который используется для форматирования строк;
- pow: оператор возведения в степень ( ** );
- complex: если вы не используете комплексные числа ( 4j + 3 ), она вам не понадобится.
Заключение
Если вы только начинаете свой путь в изучении Python, нет необходимости изучать все встроенные функции сейчас. Не торопитесь, сосредоточьтесь на первых двух пунктах (общеизвестные и упускаемые из виду), а после можете перейти и к другим, если/когда они вам понадобятся.
