Вы правы ... Декоратор - это просто синтаксический сахар. В частности:
@decorator
def foo():
pass
является точно то же самое:
def foo():
pass
foo = decorator(foo)
Давайте немного более диковинные и переписать это еще один способ, который в основном эквивалент :
def bar():
pass
foo = decorator(bar)
del bar
Надеемся, что так получилось, что вы можете видеть, что если Я звоню foo
кучу раз, я не звонил decorator
кучу раз. decorator
получил только один раз (чтобы помочь создать foo
).
Теперь в вашем примере, ваш декоратор создает список сразу, когда она вызывается:
def my_dec(f):
lst = list() # list created here!
@wraps(f)
def wrapper(*args):
lst.append(random.randint(0, 9))
print(lst)
return f(*args)
return wrapper
Функция вернула wrapper
получает назначение на ваш foo
, поэтому, когда вы звоните foo
, вы звоните wrapper
. Обратите внимание: нет кода в wrapper
, который бы сбросил lst
- только код, который добавит больше элементов в lst
, поэтому здесь нет ничего, чтобы указать lst
должно получить «покраснение» между вызовами.
(в зависимости от того, что делает декоратор, вы можете увидеть некоторые различия в атрибуте функция в __name__
, но в остальном это то же самое ...)
Также обратите внимание, что вы» У меня есть один lst
для каждого вызова декоратора. Мы можем сойти с ума с этим, если мы, как и украсить foo
дважды:
@my_dec
@my_dec
def foo():
pass
Или мы можем украсить более чем одну функцию:
@my_dec
def foo():
pass
@my_dec
def bar():
pass
И тогда, когда мы называем foo
и bar
, мы будем видеть, что каждый из них накапливает свои (отдельные) списки случайных чисел.Другими словами, каждый раз, когда ваш декоратор применяется к чему-то, будет создан новый список, и каждый раз, когда вызывается «что-то», список будет расти.
Вы правы, что декоратор является просто синтаксическим сахаром для 'foo = my_dec (foo)' ... Но я не вижу, как это приведет вас к мысли, что 'lst' будет« покрасневшим ». Будьте осторожны: «my_dec» вызывается только один раз, независимо от того, сколько раз вы называете 'foo' ... – mgilson
О да, вы правы. Я думал, что 'my_dec' вызывается каждый раз, когда вызывается' foo', но, очевидно, это не так, поскольку 'foo = my_dec (foo)' происходит только один раз. Спасибо за разъяснения! – daniel451
Дополнительный вопрос: могу ли я получить доступ к 'lst' каким-то образом? – daniel451