简体   繁体   English

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

[英]Python: Overload Instance Method and Class Method/ Access Instance Variable from Class Method

I was wondering what the best way to implement the following design would be in 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}")

I want to be able to access the method both as an instance method that uses the value the object was initialised with, and as a class method which uses a passed in variable.我希望能够访问该方法,既可以作为使用 object 初始化的值的实例方法,也可以作为使用传入变量的 class 方法访问该方法。 Here is an example of the ways in which I would like to call it:这是我想调用它的方式的示例:

>>> 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'

I was thinking about trying to use keyword arguments, but I can't seem to get that to work either.我正在考虑尝试使用关键字 arguments,但我似乎也无法让它工作。 Here is my code so far:到目前为止,这是我的代码:

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.

But the class instance does not have the val available for access.但是 class 实例没有可供访问的 val。

The only other thing I can think of is using Hungarian notation, but it's not ideal as it's a bit messy, and it means there's multiple method names.我唯一能想到的另一件事是使用匈牙利符号,但这并不理想,因为它有点混乱,这意味着有多个方法名称。

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

Any advice on a solid, clean approach would be greatly appreciated!任何关于可靠、干净的方法的建议将不胜感激!

Cheers.干杯。

What you want to do looks strange to me, I am not sure you need that.你想做的事情对我来说很奇怪,我不确定你是否需要。 Python cannot overload by method signatures/type, although there is the functools.singledispatch . Python 不能通过方法签名/类型重载,尽管有functools.singledispatch So by defining action a second time you are actually replacing the first definition for the method.因此,通过第二次定义action ,您实际上是在替换方法的第一个定义。

The observable behaviour can be achieved with:可观察的行为可以通过以下方式实现:

class Executor:

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

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

Outputs:输出:

5
3

But again check first that you really need something like that, because it breaks one of the expectations of Python coders and Python data model: calling a method through the class is equivalent to calling the method through the instance given that you pass the instance to the class method. But again check first that you really need something like that, because it breaks one of the expectations of Python coders and Python data model: calling a method through the class is equivalent to calling the method through the instance given that you pass the instance to the class 方法。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM