微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Python:重载实例方法和类方法/从类方法访问实例变量

如何解决Python:重载实例方法和类方法/从类方法访问实例变量

我想知道在 Python 中实现以下设计的最佳方法是什么:

class Executor:
    def __init__(self):
        self.val = 5

    def action(self):
        self.action(self.val)

    @classmethod
    def action(cls,val):
        print(f"Val is: {val}")

我希望能够以使用对象初始化值的实例方法和使用传入变量的类方法访问该方法。下面是我想调用它的方式的一个例子:

>>> Executor.action(3)
Val is: 3
>>> Executor().action()
Traceback (most recent call last):
  File "<input>",line 1,in <module>
TypeError: action() missing 1 required positional argument: 'val'

我正在考虑尝试使用关键字参数,但我似乎也无法让它发挥作用。到目前为止,这是我的代码

class Executor:
    def __init__(self):
        self.val = 5

    @classmethod
    def action(cls,val=None):
        if val is None:
            # This doesn't work; cls does not have attribute 'val'.
            if hasattr(cls,"val"):
                print(f"Val from instance: {cls.val}")

            else:
                raise ValueError("Called as class method and val not passed in.")

        else:
            print(f"Val passed in: {val}")


>>> Executor.action(3)
Val passed in: 3
>>> Executor().action()
Traceback (most recent call last):
  File "<input>",in <module>
  File "<input>",line 13,in action
ValueError: Called as class method and val not passed in.

但是类实例没有可访问的 val。

我能想到的唯一的另一件事是使用匈牙利表示法,但这并不理想,因为它有点凌乱,而且这意味着有多个方法名称

class Executor:
    def __init__(self):
        self.val = 5

    def action_instance(self):
        self.action_class(self.val)

    @classmethod
    def action_class(cls,val):
        print(f"Val is: {val}")


>>> Executor.action_class(3)
Val is: 3
>>> Executor().action_instance()
Val is: 5

对于可靠、干净的方法的任何建议将不胜感激!

干杯。

解决方法

我觉得你想做的事情很奇怪,我不确定你是否需要那个。 Python 不能通过方法签名/类型重载,尽管有 functools.singledispatch。因此,通过第二次定义 action,您实际上是在替换该方法的第一个定义。

可以通过以下方式实现可观察的行为:

class Executor:

    @classmethod
    def action(cls,val=5):
        return val

print(Executor().action())
print(Executor.action(3))

输出:

5
3

但再次检查您是否真的需要这样的东西,因为它打破了 Python 编码人员和 Python 数据模型的期望之一:通过类调用方法等同于通过实例调用方法,前提是您传递了类方法的实例。

obj = Executor()
obj.action() # this is the same as Executor.action(obj)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。