Вот полностью инкапсулированная версия, которая не требует внешнего вызова инициализации:
def fn():
fn.counter=vars(fn).setdefault('counter',-1)
fn.counter+=1
print (fn.counter)
В Python функции являются объектами, и мы можем просто добавить или исправить патч переменные-члены к ним через специальный атрибут __dict__
. Встроенный vars()
возвращает специальный атрибут __dict__
.
РЕДАКТИРОВАТЬ: Обратите внимание, в отличие от альтернативного ответа try:except AttributeError
, при таком подходе переменная всегда будет готова для логики кода после инициализации. Я думаю, что try:except AttributeError
альтернатива следующему будет менее СУХОЙ и / или иметь неловкий поток:
def Fibonacci(n):
if n<2: return n
Fibonacci.memo=vars(Fibonacci).setdefault('memo',{}) # use static variable to hold a results cache
return Fibonacci.memo.setdefault(n,Fibonacci(n-1)+Fibonacci(n-2)) # lookup result in cache, if not available then calculate and store it
РЕДАКТИРОВАТЬ2: Я рекомендую вышеупомянутый подход только тогда, когда функция будет вызываться из нескольких мест. Если вместо этого функция вызывается только в одном месте, лучше использовать nonlocal
:
def TheOnlyPlaceStaticFunctionIsCalled():
memo={}
def Fibonacci(n):
nonlocal memo # required in Python3. Python2 can see memo
if n<2: return n
return memo.setdefault(n,Fibonacci(n-1)+Fibonacci(n-2))
...
print (Fibonacci(200))
...