Закрытие
Закрытие означает, что другая функция определена в одной функции, временная переменная внешней функции используется во внутренней функции, а возвращаемое значение внешней функции является ссылкой на внутреннюю функцию, которая представляет собой замыкание. Например следующее:
def callFunc():
n = 1
def show():
print('show: ', n)
return show
s = callFunc()
s()
Убрано использование глобальных переменных. А функция show инкапсулирована внутри функции callFunc, так что снаружи она невидима, функцию show использовать нельзя, а детали реализации скрыты
Когда программа выполняется, функция callFunc возвращаетВнутреннее определениефункция шоу, а в функции шоувнутреннее использованиепеременные внешней функции.
Когда функция show возвращает значение, текущая среда выполнения сохраняется, то есть внешняя переменная n, которая будет использоваться в функции show.
Поскольку n является локальной переменной в функции callFunc, при нормальных обстоятельствах после завершения выполнения функции callFunc n будет освобожден.
Но теперь, поскольку функция show возвращается в функцию callFunc, функция show снова будет выполняться снаружи, поэтому программа сохранит среду выполнения, необходимую для функции show.
Эта форма называется замыканием.
декоратор
Декоратор сам по себе тоже является функцией, его функция заключается в добавлении некоторых функций для украшения существующих функций без изменения функций.
На самом деле декоратор — это функция, которая определяется и используется в виде замыкания.имя функции @decoratorформа для украшения.
Например, в проекте сейчас много функций, по мере того, как проект становится все больше и больше, функций становится все больше и больше, что делает программу все медленнее и медленнее.
Одна из функций функции реализует накопление в миллион раз.
def my_count():
s = 0
for i in range(1000001):
s += i
print('sum : ', s)
Теперь я хочу рассчитать время работы функции, как это решить? Как это можно применить ко всем функциям?
Решение:
import time
def count_time(func):
def wrapper(): #wrapper 装饰
start = time.time()
func()
end = time.time()
print('共计执行:%s 秒'%(end - start)) # 使用%d显示,取整后是0秒,因为不到一秒
return wrapper
@count_time # 这实际就相当于解决方法3中的 my_count = count_tiem(my_count)
def my_count():
s = 0
for i in range(10000001):
s += i
print('sum : ', s)
my_count()
Преимущество этой реализации в том, что после определения функции закрытия. просто пройти@xxxФормальный синтаксис декоратора, просто добавьте @xxx перед украшаемой функцией.
Универсальный декоратор
def setFunc(func):
def wrapper(*args, **kwargs): # 接收不同的参数
print('wrapper context')
return func(*args, *kwargs) # 再原样传回给被装饰的函数
return wrapper
@setFunc
def show(name, age):
print(name,age)
show('tom',12)
Получайте различные типы параметров с помощью аргументов с переменным числом аргументов и ключевых слов.
Класс реализует декоративную форму
Форма декоратора также может быть реализована через определение класса.
Реализовано в классе с помощью методов __init__ и __call__
class Test(object):
# 通过初始化方法,将要被装饰的函数传进来并记录下来
def __init__(self, func):
self.__func = func
# 重写 __call__ 方法来实现装饰内容
def __call__(self, *args, **kwargs):
print('wrapper context')
self.__func(*args, **kwargs)
# 实际通过类的魔法方法call来实现
@Test # --> show = Test(show) show由原来引用函数,装饰后变成引用Test装饰类的对象
def show():
pass
show() # 对象调用方法,实际上是调用魔法方法call,实现了装饰器