gpt4 book ai didi

python - 创建一个既是类方法又是实例方法的方法

转载 作者:太空宇宙 更新时间:2023-11-04 09:48:40 24 4
gpt4 key购买 nike

在 Python 中有没有一种方法可以定义一个既是类方法又是实例方法的方法,使得 clsself 都是接收者。特别是,我希望创建一个方法,(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.methodFoo().method)。该方法将实例和类作为参数传递并返回一个绑定(bind)方法(即它返回一个带有clsself参数的方法烘烤)。调用此绑定(bind)方法时,它将内置的 clsself 参数转发给实际方法。

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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com