Автор оригинала: Moyosore Sosan.
Мы будем рассматривать локальные функции, концепции закрытия и то, что такое декораторы, звучит как много? Тогда давайте погрузимся в это.
Локальные функции
Вероятно, большинство функций, с которыми вы знакомы, определены либо в модуле/глобальной области, либо в классах, т. Е. методах. Однако Python позволяет нам определять наши функции в локальной области, то есть внутри функции. Зная это, локальные функции-это функции, определенные в другой функции. Мы говорим, что эти функции определены в рамках конкретной функции, например
def my_function(): def my_local_function(): print('I am a local function, local to my_function') print('I am not a local function')
Функция my_local_function является локальной функцией, поскольку она доступна только внутри my_function
и может использоваться только внутри функции. Давайте рассмотрим другой пример:
def remove_first_item(my_array): def get_first_item(s): return s[0] my_array.remove(get_first_item(my_array)) return my_array print(remove_first_item(['1','2','3']))) # ['2','3'] print(get_first_item([1,2,3,4])) # NameError: name 'get_first_item' is not defined
Из вышесказанного мы видим, что вызов get_first_item выдает ошибку. Это связано с тем, что он может быть доступен только в функции remove_first_item , что делает его локальной функцией.
Локальные функции также могут быть возвращены из функций. Возврат локальной функции аналогичен возврату в любом другом объекте. Давайте посмотрим:
def enclosing_func(): def local_func(): print ('I am a local function') return local_func() print(enclosing_func()) # I am a local function'
Локальные функции подчиняются тем же правилам области видимости, что и другие функции, это приводит к правилу LEGB
для поиска имен в python – проверка начинается с локальной области, затем с заключающей, затем глобальной и, наконец, встроенной области LEGB- Локальной, Эклектичной, глобальной, встроенной
x = 'global' def outer_func(): y = 'enclose' def inner_func(): z = 'local' print(x, y, z) inner_func() print(outer_func()) # global enclose local
Локальные функции могут использоваться, когда есть необходимость в специализированных функциях. Они также помогают с организацией кода и удобочитаемостью.
Закрытие
Локальные функции, которые мы рассматривали до сих пор, не имеют определенного способа взаимодействия с окружающей областью, которая вот-вот изменится. Локальные функции могут использовать переменные в своей охватывающей области, правило LEGB
делает это возможным.
def outer_func(): x = 5 def inner_func(y = 3): return (x + y) return inner_func a = outer_func() print(a()) # 8
Из вышесказанного мы видим, что функция inner_func ссылается на функцию outer_func для значения x. Локальная функция может ссылаться на внешнюю область через closures
. Замыкания поддерживают ссылки на объекты из более ранней области.
Закрытие обычно используется в том, что называется Function Factory – это функции, которые возвращают другие функции. Возвращаемые функции являются специализированными. Фабрика функций принимает аргументы, создает локальную функцию, которая создает свои собственные аргументы, а также использует аргументы, переданные фабрике функций. Это возможно при закрытии
def multiply_by(num): def multiply_by_num(k): return num * k return multiply_by_num five = multiply_by(5) print(five(2)) # 10 print(five(4)) # 20 decimal = multiply_by(10) print(decimal(20)) # 200 print(decimal(3)) # 30
Здесь мы видим, что локальная функция multiply_by_num принимает аргумент k
и возвращает аргумент, умноженный на аргумент ее заключающей функции. Кроме того, функция multiply_by принимает аргумент num
и возвращает функцию, которая умножает num
на свой аргумент.
Правило LEGB не применяется при появлении новых привязок имен
text = "global text" def outer_func(): text = "enclosing text" def inner_func(): text = "inner text" print('inner_func:', text) # inner_func: global text print('outer_func:', text) # outer_func: enclosing text inner_func() print('outer_func:', text) # outer_func: enclosing text print('global:', text) # global: global text outer_func() print('global:', text) # global: global text
В функции inner_func мы создали новую привязку имени, переназначив переменную text
в области действия функции. Вызов inner_func не влияет на переменную text
в outer_func , аналогично вызов outer_func не влияет на глобальную переменную text
.
глобальный
global
– это ключевое слово python, которое вводит имена из глобального пространства имен в локальное пространство имен. Из предыдущего кода мы можем сделать inner_func , чтобы изменить переменную text
, а не создавать новую.
text = "global text" def outer_func(): text = "enclosing text" def inner_func(): global text # binds the global text to the local text text = "inner text" print('inner_func:', text) # inner_func: inner text print('outer_func:', text) # outer_func: enclosing text inner_func() print('outer_func:', text) # outer_func: enclosing text print('global:', text) # global: global text outer_func() print('global:', text) # global: inner text
Поскольку ключевое слово global
связало глобальную text
переменную с локальной text
переменной, вызов функции outer_func вносит изменения в глобальный текст, следовательно, переназначая переменную text
в глобальной области.
нелокальный
Ключевое слово nonlocal
позволяет нам вводить имена из окружающего пространства имен в локальное пространство имен. Все еще глядя на предыдущий код:
text = "global text" def outer_func(): text = "enclosing text" def inner_func(): nonlocal text # binds the local text to the enclosing text text = "inner text" print('inner_func:', text) # inner_func: inner text print('outer_func:', text) # outer_func: enclosing text inner_func() print('outer_func:', text) # outer_func: inner text print('global:', text) # global: global text outer_func() print('global:', text) # global: global text
Здесь заключающая переменная text
изменяется при вызове inner_func .
Декораторы
Поскольку у нас есть понимание локальных функций и замыкания, мы можем посмотреть на декораторов функций. Декораторы используются для улучшения существующих функций без изменения их определения. Декоратор сам по себе является вызываемым объектом и принимает другой вызываемый объект, чтобы вернуть другой вызываемый объект. Проще говоря, декоратор – это функция, которая принимает другую функцию и возвращает другую функцию, хотя это немного больше, чем просто это.
# Syntax for decorator @my_decorator def my_function(): pass
Результат вызова my_function передается в my_decorator
def capitalize(func): def uppercase(): result = func() return result.upper() return uppercase @capitalize def say_hello(): return "hello" print(say_hello()) # 'HELLO'
Результат вызова say_hello передается в декоратор с заглавной буквы. Декоратор изменяет функцию say_hello , изменяя ее результат на верхний регистр. Мы видим, что декоратор capitalize принимает вызываемый объект(say_hello) в качестве аргумента и возвращает другой вызываемый объект(верхний регистр). Это всего лишь базовый пример на декораторе
В следующем посте мы продолжим разбираться в том, как декораторы работают в python. Чтобы подготовиться к этому, давайте кратко рассмотрим *args и **kwargs
*арги и **кварги
*args
позволяет использовать любое количество аргументов в функции. Вы используете его, когда не уверены, сколько аргументов может быть передано в функцию
def add_all_arguments(*args): result = 0 for i in args: result += i return result print(add_all_arguments(1,5,7,9,10)) # 32 print(add_all_arguments(1,9)) # 10 print(add_all_arguments(1,2,3,4,5,6,7,8,9,10)) # 55 print(add_all_arguments(1)) # 1 print(add_all_arguments()) # 0
Например, *args
, **kwargs
может принимать много аргументов, которые вы хотели бы ему предоставить. Однако **kwargs
отличается от *args
тем, что вам нужно будет назначить ключевые слова
def print_arguments(**kwargs): print(kwargs) print(print_arguments(name = 'Moyosore')) # {'name': 'moyosore'} print(print_arguments(name = 'Moyosore'), country = 'Nigeria') print(print_arguments()) # {} # {'name': 'moyosore', 'country': 'Nigeria'} def print_argument_values(**kwargs): for key, value in kwargs.items(): print('{0}: {1}'.format(key, value)) print_argument_values(name="Moyosore", country="Nigeria") # name: Moyosore # country: Nigeria
Args и kwargs могут использоваться вместе в функции, причем args всегда предшествуют kwargs. Если есть какие-либо другие требуемые аргументы, они предшествуют args и kwargs
def add_and_mul(*args, **kwargs): pass def add_and_mul(my_arg, *args, **kwargs): pass def add_and_mul(my_arg, my_arg_1, *args, **kwargs): pass
Вы можете больше читать об args и кваргах для лучшего понимания. Это всего лишь пример для вас, чтобы иметь базовое представление об args и кваргах.
Следующий пост будет посвящен декораторам в деталях!