我有一个我之前创建的Python类,它看起来像这样:
class Foo:
@classmethod
def bar(cls, x):
print(x + 3)
Foo.bar(7) # prints '10'
现在我想用一些状态来改进这个接口,以便调用者可以创建一个Foo
对象,给它一些属性,然后调用它的bar()
方法,该方法可以访问{ {1}}及其属性:
self
不幸的是,这打破了之前的界面 - class Foo:
def __init__(self, y=3):
self.y = y
def bar(self, x):
print(x + self.y)
Foo().bar(7) # prints '10'
Foo(20).bar(7) # prints '27'
现在会提供Foo.bar(7)
,因为TypeError: bar() missing 1 required positional argument: 'x'
是一个简单的函数参考。
我可以添加一个Foo.bar(...)
装饰器来获得部分:
@classmethod
是否可以创建一个转换另一个方向的class Foo:
def __init__(self, y=3):
self.y = y
@classmethod
def bar(cls, x):
self = cls()
print(x + self.y)
Foo.bar(7) # prints '10'
Foo().bar(7) # prints '10'
Foo(20).bar(7) # prints '10', but I want '27'
装饰器?具体来说 - 如果作为@flexmethod
之类的实例方法调用,则不执行任何操作;如果被调用为Foo(20).bar(...)
之类的类方法,则创建一个新的Foo.bar(...)
对象(使用no-arg构造函数)并将其作为Foo
参数传递。
我打算通过查看self
的来源自己尝试一下,但看起来它是在C级实现的。
答案 0 :(得分:1)
Descriptor HOWTO包含@classmethod
和@staticmethod
如何工作的完整部分,以及如何实现它们的变体,包括与classmethod
等效的纯Python:
class ClassMethod(object):
"Emulate PyClassMethod_Type() in Objects/funcobject.c"
def __init__(self, f):
self.f = f
def __get__(self, obj, klass=None):
if klass is None:
klass = type(obj)
def newfunc(*args):
return self.f(klass, *args)
return newfunc
如果你不明白它是如何工作的,你可能需要阅读整个HOWTO。我有a blog post试图首先介绍与方法相关的东西,这可能有助于克服HOWTO第一部分的抽象概念。