【问题标题】:return something other than the object on creation of object在创建对象时返回对象以外的东西
【发布时间】:2012-03-15 14:28:20
【问题描述】:

我想创建一个知道不基于输入参数实例化的类。举个简单的例子,如果我想创建一个对象,该对象只有在其输入参数之一 > 1 时才能存在,那么

foo = new_object(0.1)

应该将None返回到foo而不是对象。

我觉得它是一种创建对象的优雅方式,因为这意味着我不需要类外的代码来决定是否创建它

有没有办法做到这一点,或者同样有用,这是不好的做法,为什么?

【问题讨论】:

  • 提高 ValueError 将是 Pythonic 解决方案。
  • 引发异常是通常的路线,但不是唯一的路线。还有其他 Pythonic 解决方案。
  • 但是如果你想返回初始化失败原因的具体信息,你可以例外吗

标签: python class object initialization


【解决方案1】:

您需要覆盖__new__——确保它采用与__init__相同的参数:

class Test(object):
    def __init__(self, value):
        self.value = value
    def __new__(cls, value):
        if value > 1:
            return object.__new__(cls)
        return None
    def __repr__(self):
        return "Test value %d" % self.value


t1 = Test(2)
print repr(t1)
t2 = Test(1)
print repr(t2)

Python 支持从 __new__ 返回不同类型的对象,但这种做法相当罕见。

在您的用例中,如果您在两者之间进行选择

if value < 1:
    foo = None
else:
    foo = Test(value)

foo = Test(value)  # will None if value <= 1

这是你必须做很多次的事情,那么我肯定会考虑让全班来做。

在您无法控制new_object 的情况下,您可以创建自己的工厂函数:

def maybe_foo(value):
    if value > 1:
        return new_object(value)
    return None

【讨论】:

    【解决方案2】:

    您可以覆盖__new__() 以有效地将对象实例化转换为您想要在此处执行的类似工厂的操作。我有时喜欢使用抽象基类的__new__() 作为具体子类的工厂,只要具体子类的列表可以被限制和知道。只要确保它是您问题的最佳解决方案,因为它可能不是...

    【讨论】:

      【解决方案3】:

      很明显,这将是一个不好的做法,原因很简单,没有人会这样做。调用构造函数应该是构造对象实例,而不是选择性地决定它是否想要。在构造对象时,您不应该需要检查失败。所以它有一个相当高的“wtf配额”,这绝不是一个好主意。

      也就是说,我不确定这是否可能,因为__init__() 在实例已经创建之后在实例上运行(并且不以return self 结尾)。这是Python,我敢肯定有些事情可以争论。我的观点是,这样做是个坏主意。

      【讨论】:

      • “没有人这样做”使这种做法很少见,不一定是坏事。 __init__ 是初始化器,仅当 __new__(构造函数)返回与其所属的类相同的类型时才会调用它。
      猜你喜欢
      • 1970-01-01
      • 2013-08-23
      • 1970-01-01
      • 1970-01-01
      • 2017-10-06
      • 1970-01-01
      • 2019-01-17
      • 2016-01-30
      • 2010-09-27
      相关资源
      最近更新 更多