【问题标题】:Python: Overload Instance Method and Class Method/ Access Instance Variable from Class MethodPython:重载实例方法和类方法/从类方法访问实例变量
【发布时间】:2021-06-03 10:47:48
【问题描述】:

我想知道在 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>", line 1, 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 overloading instance-variables class-method instance-methods


    【解决方案1】:

    你想做的事情对我来说很奇怪,我不确定你是否需要。 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)
    

    【讨论】:

      猜你喜欢
      • 2017-03-20
      • 2015-07-09
      • 1970-01-01
      • 1970-01-01
      • 2017-02-15
      • 2017-05-12
      • 1970-01-01
      • 1970-01-01
      • 2014-01-26
      相关资源
      最近更新 更多