首页 > 解决方案 > 如何将一个方法定义为实例方法和类方法(共享相同名称),每个方法都有不同的参数?

问题描述

从本质上讲,我正在尝试完成以下操作,但在 wherebarbaz具有相同的句柄(例如 just bar)而不是两个不同命名的函数。

定义
import numpy as np
foo = np.add # For example; real function will be different in every instance

class MyClass(object):
    def __init__(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2

    def bar(self):
        return foo(self.arg1, self.arg2)

    @classmethod
    def baz(cls, arg1, arg2):
        return foo(arg1, arg2)
示例用法
a, b = 1, 2
mine = MyClass(a, b)
print(mine.bar())
>>> 3
x, y = 3, 4
print(MyClass.baz(x, y))
>>> 7

为了便于理解,我正在尝试这样做。_真正的函数名称很长,带有许多下划线,并且为我想要执行的每个函数创建两个名称略有不同的函数(例如,在一个函数名称前加上 a )只会混淆已经很复杂的情况。

该函数将主要在内部使用,但我希望能够在静态上下文中使用可能不一定与给定对象的实例变量匹配的临时参数调用该函数MyClass(事实上,我只会称它为如果他们不匹配的方式)。我使用@classmethod而不是@staticmethod因为真正的函数使用一些内部类变量。

我已经尝试简单地bar为两个函数名称实现上述内容,但正如预期的那样,实例方法已被类方法覆盖。

我看到了一些使用描述符的类似 SO 帖子的答案,但我希望可能有一个更优雅的解决方案。

这里有任何明智的 Python 向导有建议吗?

标签: pythonoopoverloadingclass-methodinstance-methods

解决方案


您也可以 letself采用默认参数,以便区分mine.bar()MyClass.bar()。代价是其他两个参数必须是关键字参数。

class MyClass:

    _sentinel = object()

    def bar(self=None, *, arg1=_sentinel, arg2=_sentinel):
        if self is not None:
            if arg1 is _sentinel:
                arg1 = self.arg1
            if arg2 is _sentinel:
                arg2 = self.arg2
        else:
            if arg1 is _sentinel:
                raise ValueError("Missing required arg1")
            if arg2 is _sentinel:
                raise ValueError("Missing required arg2")

        return foo(arg1, arg2)


mine.bar()  # self is mine, arg1 is _sentinel, arg2 is _sentinel

MyClass.bar(arg1=3, arg2=4)

推荐阅读