在 Python 中有没有一种方法可以定义一个既是类方法又是实例方法的方法,使得 cls
和 self
都是接收者。特别是,我希望创建一个方法,(1) 在类 (Foo.method(value)
) 上调用时知道调用了哪个类,并且 (2) 知道它是哪个实例在实例上调用时调用 (foo.method()
)。
例如,我会设想这样的事情:
class Foo:
def __str__(self): return 'Foo()'
@classinstancemethod
def method(cls, self):
print(cls, self)
class Bar(Foo):
def __str__(self): return 'Bar()'
Foo().method() # <class '__main__.Foo'> Foo()
Bar().method() # <class '__main__.Bar'> Bar()
Foo.method(Foo()) # <class '__main__.Foo'> Foo()
Foo.method(Bar()) # <class '__main__.Foo'> Bar()
Bar.method(Foo()) # <class '__main__.Bar'> Foo()
请注意,我知道可以像 Foo.foo(value)
那样调用未修饰的方法,但这不是我想要的,因为它没有得到 cls
变量。如果没有 cls
变量,该方法就不知道它刚刚调用的是哪个类。它可能被称为 Bar.method(value)
,现在有办法知道 value
是否是 Foo
的实例.未修饰的方法更像是静态方法和实例方法,而不是类方法和实例方法。
最佳答案
这可以通过将 classinstancemethod
作为自定义实现来解决 descriptor .
简而言之,描述符必须定义一个 __get__
当它作为属性访问时将被调用的方法(如 Foo.method
或 Foo().method
)。该方法将实例和类作为参数传递并返回一个绑定(bind)方法(即它返回一个带有cls
和self
参数的方法烘烤)。调用此绑定(bind)方法时,它将内置的 cls
和 self
参数转发给实际方法。
class classinstancemethod:
def __init__(self, method, instance=None, owner=None):
self.method = method
self.instance = instance
self.owner = owner
def __get__(self, instance, owner=None):
return type(self)(self.method, instance, owner)
def __call__(self, *args, **kwargs):
instance = self.instance
if instance is None:
if not args:
raise TypeError('missing required parameter "self"')
instance, args = args[0], args[1:]
cls = self.owner
return self.method(cls, instance, *args, **kwargs)
结果:
class Foo:
def __repr__(self): return 'Foo()'
@classinstancemethod
def method(cls, self):
print((cls, self))
class Bar(Foo):
def __repr__(self): return 'Bar()'
Foo().method() # (<class '__main__.Foo'>, 'Foo()')
Bar().method() # (<class '__main__.Bar'>, 'Bar()')
Foo.method(Foo()) # (<class '__main__.Foo'>, 'Foo()')
Foo.method(Bar()) # (<class '__main__.Foo'>, 'Bar()')
Bar.method(Foo()) # (<class '__main__.Bar'>, 'Foo()')
关于python - 创建一个既是类方法又是实例方法的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48808788/