问题是类方法是描述符对象,而不是函数。如果您在方法中做更多的工作,您可以对这两种类型的可调用对象使用相同的装饰器,在包含 v3.x 的 Python v2.6 中。这就是我的意思:
def static_var(var_name, value):
def decorator(function):
setattr(function, var_name, value)
return function
return decorator
# apply it to method
class Circle(object):
@static_var('seed', 0)
def counter(self):
counter_method = Circle.counter.__get__(self, Circle).__func__ # added
counter_method.seed +=1
return counter_method.seed
myCircle = Circle()
print(myCircle.counter()) # 1
print(myCircle.counter()) # 2
方法版本所做的是调用描述符的__get__
方法以获取绑定的方法实例对象,然后访问其__func__
属性以获取附加了命名属性的实际函数实例。
对于 2.6 之前的 Python 版本,您需要im_func
使用__func__
.
更新:
可以通过更改装饰器来避免提到的大多数问题,以便它在调用的开头添加一个参数并编写装饰函数来引用它而不是它们自己来访问变量。另一个好处是这种方法适用于 Python 2.x 和 3.x:
def static_var(var_name, value):
def decorator(function):
static_vars = getattr(function, 'static_vars', None)
if static_vars: # already have a container?
setattr(static_vars, var_name, value) # add another var to it
return function
else:
static_vars = type('Statics', (object,), {})() # create container
setattr(static_vars, var_name, value) # add first var to it
def decorated(*args, **kwds):
return function(static_vars, *args, **kwds)
decorated.static_vars = static_vars
return decorated
return decorator
@static_var('seed', 0) # apply it to a function
def counter(static_vars):
static_vars.seed +=1
return static_vars.seed
print(counter()) # 1
print(counter()) # 2
class Circle(object):
@static_var('seed', 0) # apply it to a method
def counter(static_vars, self):
static_vars.seed +=1
return static_vars.seed
myCircle = Circle()
print(myCircle.counter()) # 1
print(myCircle.counter()) # 2
这个装饰器允许添加多个静态:
@static_var('seed', 0) # add two of them to a function
@static_var('offset', 42)
def counter2(static_vars):
static_vars.seed += 1
static_vars.offset *= 2
return static_vars.seed + static_vars.offset
print(counter2()) # 1 + 2*42 = 85
print(counter2()) # 2 + 2*84 = 170