可作为类方法或实例方法调用的函数

2024-03-29 05:02:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我以前创建了一个Python类,它看起来像这样:

class Foo:
  @classmethod
  def bar(cls, x):
    print(x + 3)

Foo.bar(7)  # prints '10'

现在我想用某种状态来改造这个接口,这样调用者就可以创建一个Foo对象,给它一些属性,然后调用它的bar()方法,它可以访问self及其属性:

^{pr2}$

不幸的是,这打破了之前的接口-Foo.bar(7)现在将给出TypeError: bar() missing 1 required positional argument: 'x',因为{}是一个简单的函数引用。在

我可以添加一个@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级别实现的。在


Tags: 对象方法self属性foo状态defbar
1条回答
网友
1楼 · 发布于 2024-03-29 05:02:55

Descriptor HOWTO有完整的章节介绍@classmethod和{}如何工作,以及如何在它们上实现变体,包括这个与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第一部分的抽象障碍。在

相关问题 更多 >