Python 在创建对象时返回对象以外的内容

Python 在创建对象时返回对象以外的内容,python,class,object,initialization,Python,Class,Object,Initialization,我想创建一个知道不基于输入参数实例化的类。举个简单的例子,如果我想创建一个对象,而该对象只有在其输入参数之一大于1时才能存在,那么 foo = new_object(0.1) 应该将None返回到foo而不是对象 它给我的印象是一种创建对象的优雅方式,因为它意味着我不需要类外的代码来决定是否创建它 有没有一种方法可以做到这一点,或者同样有用,这是一种不好的做法,为什么呢?很明显,这是一种不好的做法,原因很简单,没有人会这样做。调用构造函数应该是构造对象实例,而不是选择性地决定它是否想要。在构造

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

foo = new_object(0.1)
应该将
None
返回到
foo
而不是对象

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


有没有一种方法可以做到这一点,或者同样有用,这是一种不好的做法,为什么呢?

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


也就是说,我不确定这是否可能,因为
\uuuu init\uuuu()
是在实例创建之后在实例上运行的(并且不会以
返回self
结束)。这是Python,我相信有些东西是可以争论的。我的观点是这样做是一个坏主意。

您可以重写
\uuuuu new\uuuu()
,以有效地将对象实例化转化为您希望在此处执行的类似工厂的操作。我有时喜欢使用抽象基类的
\uuuu new\uuu()
作为具体子类的工厂,只要具体子类的列表是有限的和已知的。只需确保它是解决您的问题的最佳解决方案,因为它可能不是…

您需要覆盖
\uuuuu new\uuuu
——确保它采用与
\uuuu init\uuuu
相同的参数:

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支持从
\uuuu new\uuuu
返回不同类型的对象,但这是一种相当罕见的做法

在您的用例中,如果您在

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

引发
ValueError
将是Pythonic解决方案。引发异常是常见的途径,但不是唯一的途径。还有其他Pythonic解决方案。但是如果您想返回初始化失败原因的具体信息,您可以这样做吗?例外情况是“没有人这样做”使得这种做法很少见,不一定很糟糕
\uuuuu init\uuuuuuuuuuuuuuuuuuuuu
是初始值设定项,仅当
\uuuuuuuu new\uuuuuuuuuu
(构造函数)返回的类型与其所属的类相同时,才会调用该初始值设定项。
foo = Test(value)  # will None if value <= 1
def maybe_foo(value):
    if value > 1:
        return new_object(value)
    return None