- Типы параметров функции#
- Обязательные параметры#
- Необязательные параметры (параметры со значением по умолчанию)#
- Функции
- def
- Hello World!
- type hints
- Параметры и аргументы
- Типы аргументов
- Позиционные аргументы
- Именованные аргументы
- Аргументы по умолчанию
- Значения по умолчанию
- Mutable vs Immutable
- return
- Области видимости
- Вызываемые объекты
Типы параметров функции#
При создании функции можно указать, какие аргументы нужно передавать обязательно, а какие нет. Соответственно, функция может быть создана с:
- обязательными параметрами
- необязательными параметрами (опциональными, параметрами со значением по умолчанию)
Обязательные параметры#
Обязательные параметры — определяют, какие аргументы нужно передать функции обязательно. При этом, их нужно передать ровно столько, сколько указано параметров функции (нельзя указать большее или меньшее количество)
Функция с обязательными параметрами (файл func_params_types.py):
def check_passwd(username, password): if len(password) 8: print('Пароль слишком короткий') return False elif username in password: print('Пароль содержит имя пользователя') return False else: print(f'Пароль для пользователя username> прошел все проверки') return True
Функция check_passwd ожидает два аргумента: username и password.
Функция проверяет пароль и возвращает False, если проверки не прошли и True, если пароль прошел проверки:
In [2]: check_passwd('nata', '12345') Пароль слишком короткий Out[2]: False In [3]: check_passwd('nata', '12345lsdkjflskfdjsnata') Пароль содержит имя пользователя Out[3]: False In [4]: check_passwd('nata', '12345lsdkjflskfdjs') Пароль для пользователя nata прошел все проверки Out[4]: True
Необязательные параметры (параметры со значением по умолчанию)#
При создании функции можно указывать значение по умолчанию для параметра таким образом: def check_passwd(username, password, min_length=8) . В этом случае, параметр min_length указан со значением по умолчанию и может не передаваться при вызове функции.
Пример функции check_passwd с параметром со значением по умолчанию (файл func_check_passwd_optional_param.py):
def check_passwd(username, password, min_length=8): if len(password) min_length: print('Пароль слишком короткий') return False elif username in password: print('Пароль содержит имя пользователя') return False else: print(f'Пароль для пользователя username> прошел все проверки') return True
Так как у параметра min_length есть значение по умолчанию, соответствующий аргумент можно не указывать при вызове функции, если значение по умолчанию подходит:
In [7]: check_passwd('nata', '12345') Пароль слишком короткий Out[7]: False
Если нужно поменять значение по умолчанию:
In [8]: check_passwd('nata', '12345', 3) Пароль для пользователя nata прошел все проверки Out[8]: True
Функции
Рассмотрим простейшую функцию, которая ничего не делает.
Чтобы её объявить используйте слово def затем придумайте название — например lazy поставьте круглые скобки () и двоеточие
Общий синтаксис следующий
def имя_функции (): какой-то код
В нашем случае получается
pass означает просто продолжать код ничего не предпринимая. Он применяется далеко не во всех функциях.
Наша функция создана, иначе говоря объявлена. Это значит, что она существует где-то в коде и может что-то сделать.
Но не делает. Чтобы функция что-то делала её нужно вызвать. В нашем случае достаточно написать её имя и круглые скобки.
Если никаких ошибок не допущено вывод будет пустым
def
Ключевое слово def используется для определения новых функций.
Оно связывает объект функции с именем
Hello World!
Объявим и вызовем функцию, которая пишет Hello World!
def hello (): print(«Hello World!») hello()
Функцию не обязательно писать в одну строку. Лучше после двоеточия перейти на новую строку и сделать отступ из четырёх пробелов.
def hello (): print(«Hello World!») hello()
Напишем функцию, которая складывает два числа.
def sum ( first , second ): print (first + second) sum(3,4)
type hints
В соответствии с PEP 484 рекомендуется указывать ожидаемые типы данных как для параметров, так и для возвращаемого значения
def sum (first: float , second: float ) -> float : print (first + second) sum ( 3.0 , 4.6 )
Никаких ограничений эти подсказки не накладывают. Можно спокойно выполнить
Подсказки нужны скорее для сторонней проверки, каким-либо инструментом.
Параметры и аргументы
Параметры и аргументы это почти одно и то же, но термин параметры применяют во время объявления функции а аргументы в момент вызова.
В некоторых источниках вместо термина параметры используется термин формальные аргументы (formal arguments)
Проще всего понять на примере
def add (a, b): return a+b add( 2 , 3 )
a и b это параметры, а 2 и 3 это аргументы
Типы аргументов
Аргументы могут передаваться как позиционные (positional) и как именованные (keyword).
Позиционные аргументы
Позиционные аргументы сопоставляются с параметрами (parameter или formal argument) в соответсвии с порядком следования.
Пример передачи двух позиционных аргументов
Предположим, функция sub() вычитает из первого аргумента второй.
sub(2, 3) = -1, sub(3, 2) = 1. Порядок имеет значение
Именованные аргументы
Именованные аргументы сопоставляются с параметрами по их имени.
Пример передачи двух именованных аргументов
a = div ( divident = 4 , divisor = 2 )
Предположим, функция div() делит divident (делимое) на divisor (делитель). Порядок в котом передаются именованные аргументы не важен, значения будут присвоены по совпадении имён.
Способ, которым передаётся определённый аргумент, определяется при вызове функции.
Один и тот же аргумент может быть передан как позиционный и как именованный.
def main (): print (div()) print (div( 9 , 3 )) print (div(divisor= 5 , divident= 25 )) def div (divident= 2 , divisor= 1 ): return divident/divisor if __name__ == «__main__» : main()
Сперва нужно передавать позиционные аргументы, затем именованные
# Вызов print (div(divisor= 5 , 25)) # Приведёт к ошибке
print(div(divisor=5, 25)) ^ SyntaxError: positional argument follows keyword argument
Про передачу заранее неопределёного количества аргументов читайте статью *args **kwargs
Аргументы по умолчанию
Аргументы, у которых есть значения по умолчанию, должны быть переданы после аргументов, у которых их нет.
# Arguments with default values must come # after those without default values. def banner (message, border= «-» ): line = border * len (message) print (line) print (message) print (line) banner( «www.HeiHei.ru» ) # will use default «-» banner( «www.TopBicycle.ru» , «*» ) banner( «www.KickBrains.ru» , border= «|» )
Значения по умолчанию
Mutable vs Immutable
В качестве значений по умолчанию лучше использовать неизменяемые (immutable) объекты.
Если и использовать изменяемые объекты, то нужно понимать, что они получают значения один раз — когда интерпретатор проходит объявление функции (def)
import time print ( «time.ctime()» , time.ctime()) def show_default (arg=time.ctime()): print (arg) show_default() time.sleep( 2 ) print ( «time.ctime()» , time.ctime()) show_default()
time.ctime() Wed Jun 8 11:16:04 2022 Wed Jun 8 11:16:04 2022 time.ctime() Wed Jun 8 11:16:0 6 2022 Wed Jun 8 11:16:0 4 2022
Как видно из вывода в терминал — время уже ушло вперёд — 11:16:0 6 а функция как возвращала значение по умолчанию созданное в 11:16:0 4 так и продолжает это делать.
Рассмотрим ещё один пример. Теперь в качестве изменяемого объекта возьмём список
def add_spam (menu=[]): menu.append( «spam» ) return menu breakfast = [ ‘bacon’ , ‘eggs’ ] print (add_spam(breakfast)) lunch = [ ‘borsh’ ] print (add_spam(lunch)) print (add_spam()) print (add_spam()) print (add_spam())
[‘bacon’, ‘eggs’, ‘spam’] [‘borsh’, ‘spam’] [‘spam’] [‘spam’, ‘spam’] [‘spam’, ‘spam’, ‘spam’]В первых двух случаях (завтрак и обед) функция работает как задумано. Но, если вызвать её без аргументов создасться пустой список и он не будет пересоздан — в него просто добавляются новые и новые элементы.
Решить эту проблему можно сделав аргумент по умолчанию неизменяемым
def add_spam (menu= None ): if menu is None : menu = [] menu.append( «spam» ) return menu breakfast = [ ‘bacon’ , ‘eggs’ ] print (add_spam(breakfast)) lunch = [ ‘borsh’ ] print (add_spam(lunch)) print (add_spam()) print (add_spam()) print (add_spam())
[‘bacon’, ‘eggs’, ‘spam’] [‘borsh’, ‘spam’] [‘spam’] [‘spam’] [‘spam’]return
Рассмотрим скрипт test_return.py
def test_return (): return «A» v = test_return() print (v)
Всё выглядит хорошо, функция вернула строку, мы видим её в терминале.
Но что будет, если эту функцию импортировать, а не вызвать в том же скрипте
return_ex ├── parent_test_return.py └── test_return.py 0 directories, 2 files
# test_return def test_return (): return «A»
# parent_test_return from test_return import test_return v = test_return() print (v)
Области видимости
Рассмотрим четыре стандартные области видимости
Эта четвёрка описывается акронимом LEGB
Области видимости не имеют прямой связи с блоками кода.
Например, цикл for, хотя и нуждется в дополнительном отступе, не вводит новых областей видимости.
count = 0 def show_count (): print (count) def set_count (c): count = c show_count() # 0 set_count( 5 ) show_count() # 0
count = 0 def set_count (c): global count count = c show_count() # 0 set_count( 5 ) show_count() # 0
Продолжить изучение областей видимости функции можно в статье о локальных функциях замыкания: области видимости
Вызываемые объекты
Рассмотрим файл callables.py
def is_even (x): return x % 2 == 0 print ( callable (is_even)) # True is_odd = lambda x: x % 2 == 1 print ( callable (is_odd)) # True # Classes are callable print ( callable ( list )) # True # Methods are callable print ( callable ( list .append)) # True class CallMe : def __call__ (self): print ( «Called!» ) my_call_me = CallMe() print ( callable (my_call_me)) # True # Strings are not callable print ( callable ( «This is no callable» )) # False
True True True True True False
from functools import reduce import operator print (operator.add( 8 , 9 )) print ( reduce (operator.add, [ 1 , 2 , 3 , 4 , 5 ])) numbers = [ 1 , 2 , 3 , 4 , 5 ] accumulator = operator.add(numbers[ 0 ], numbers[ 1 ]) for item in numbers[ 2 :]: accumulator = operator.add(accumulator, item) print (accumulator) def mul (x, y): print (f «mul » ) return x * y print ( reduce (mul, range ( 1 , 10 ))) # reduce(mul, []) # TypeErr reduce (mul, [ 1 ]) # returns element without calling reduce print ( reduce (mul, [ 1 ])) # 1 # Initial value is added as a first accumulated value values = [ 1 , 2 , 3 ]
17 15 15 mul 1 2 mul 2 3 mul 6 4 mul 24 5 mul 120 6 mul 720 7 mul 5040 8 mul 40320 9 362880 1 6 0 6