Python 可作为类方法或实例方法调用的函数
我有一个我以前创建的Python类,它看起来像这样:Python 可作为类方法或实例方法调用的函数,python,function,methods,class-method,instance-methods,Python,Function,Methods,Class Method,Instance Methods,我有一个我以前创建的Python类,它看起来像这样: class Foo: @classmethod def bar(cls, x): print(x + 3) Foo.bar(7) # prints '10' 现在我想用一些状态来改进这个接口,这样调用者就可以创建一个Foo对象,给它一些属性,然后调用它的bar()方法,该方法可以访问self及其属性: class Foo: def __init__(self, y=3): self.y = y def b
class Foo:
@classmethod
def bar(cls, x):
print(x + 3)
Foo.bar(7) # prints '10'
现在我想用一些状态来改进这个接口,这样调用者就可以创建一个Foo
对象,给它一些属性,然后调用它的bar()
方法,该方法可以访问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()缺少1个必需的位置参数:“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(…)
,则创建一个新的Foo
对象(不使用参数构造函数),并将其作为self
参数传递
我本打算亲自查看@classmethod
的源代码来尝试这一点,但它看起来是在C级实现的。这一节完整地介绍了@classmethod
和@staticmethod
的工作原理,以及如何在它们上实现变体,将此纯Python等效于classmethod
:
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。我想先介绍一下与方法相关的东西,这可能有助于克服HOWTO第一部分的抽象困难。标记为“完全重复”的问题是不同的——用我的话来说,就是如何获得
Foo(20.bar)
和Foo.bar(20.7)
,使其表现相同,我的是关于Foo.bar(7)
和Foo.bar(7)
。区别很重要,因为整个要点是保持现有的接口Foo.bar(7)
。刚刚实现-尽管问题不同,@user2357112的解决方案也包括我问题的解决方案。明天上班的时候我会试试看。谢谢,我会努力解决这个问题,看看能不能想出点什么办法。如果我这样做了,我会把它作为一个新的答案发布。