【问题标题】:Calling other class methods from __new__() in python在 python 中从 __new__() 调用其他类方法
【发布时间】:2018-10-27 14:50:04
【问题描述】:

我创建了一个类foo,如下所示:

class foo():

    def __new__(cls, a, b, c, add=True):
        return cls.sum(a, b, c) if add else cls.subtract(a, b, c)

    def sum(a, b, c):
        return a + b + c

    def subtract(a, b, c):
        return c - b - a

print(foo(1, 2, 3, True))

此程序将所需结果返回为6。但是,我需要弄清一些概念:

  1. 使用这种方法或 OOP 设计是否正确,或者有更好的方法吗?我希望该类返回一个值或任何其他对象(不是它自己的类实例)
  2. 无论上面的结构如何,如果sumsubtract是实例方法,如何在不实例化对象的情况下调用它们,如上例即print(...)

我观察到许多 python API 和框架通过类实例化返回一个对象或一个值。

我正在尝试理解 Python 中 OOP 的核心概念,请帮助。

【问题讨论】:

  • 使用foo(1, 2, 3, True),您正在实例化对象
  • 然而,在使用 PyCharm 时,它会显示一个错误(在编辑过程中)......但它会运行。这实际上让人感到困惑......然后我猜这是 PyCharm 的错误建议......
  • 什么错误?请记住,PyCharm 试图猜测当代码实际运行而不实际运行时会发生什么。从我在这里读到的所有内容来看,它做得并不好。
  • 为什么这是一个类?函数更有意义。
  • 我同意。错误/建议是它要求您将self 添加到addsubtract 方法,但是当我添加它们时,程序会抛出Missing Argument 错误。这让我想知道addsubtract 是否是实例方法。

标签: python python-3.x class oop


【解决方案1】:

按照您现在的方式,sumsubtract 确实是实例方法。

>>> foo_obj = object.__new__(foo)  # This will actually create a foo object to demonstrate
>>> foo_obj.sum
<bound method foo.sum of <__main__.foo object at 0x0000000000000000>>
>>> type(foo_obj.sum)
<class 'method'>

但这只是因为当你通过实例访问它们时,Python 会动态创建一个方法(基本上只是将第一个参数绑定到对象,通常是self

但是,你可以通过类访问被包装的函数:

>>> foo_obj.sum.__func__
<function foo.sum at 0x0000000000000001>
>>> foo.sum
<function foo.sum at 0x0000000000000001>
>>> foo_obj.sum.__func__ is foo.sum
True

所以在您的__new__ 函数中,它不会绑定第一个参数,并且它们调用底层函数而不是使它们成为实例方法。

要修复警告,您可以将它们设为classmethods 或staticmethods。但是,不从__new__ 返回作为类实例的对象通常是不好的做法。如果你真的想使用 OOP,要么继承 int,要么制作一个包装器,这样你就可以拥有:

>>> class Foo:
    __slots__ = 'value',
    def __init__(self, a, b, c, add=True):
        self.value = self.sum(a, b, c) if add else self.subtract(a, b, c)
    @staticmethod
    def sum(a, b, c):
        return a + b + c
    @staticmethod
    def subtract(a, b, c):
        return c - b - a
>>> foo = Foo(1, 2, 3, True)
>>> foo
<__main__.foo object at 0x0000000000000002>
>>> foo.value
6

>>> class Foo(int):
    __slots__ = ()
    def __new__(cls, a, b, c, add=True):
        value = cls.sum(a, b, c) if add else cls.subtract(a, b, c)
        return super().__new__(cls, value)
    @staticmethod
    def sum(a, b, c):
        return a + b + c
    @staticmethod
    def subtract(a, b, c):
        return c - b - a
>>> foo = Foo(1, 2, 3, True)
>>> foo
6
>>> type(foo)
<class '__main__.Foo'>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 2011-07-04
    相关资源
    最近更新 更多