使用__new__从现有对象中获取Python对象

时间:2012-09-30 05:12:53

标签: python object types instantiation

在学习Python的数据模型时,我正在使用__new__方法从现有对象创建对象。以下是一些创建各种类型的新对象的示例:

x = 2;     print type(x).__new__(x.__class__)
x = {};    print type(x).__new__(x.__class__)
x = [1,2]; print type(x).__new__(x.__class__)
x = 2.34;  print type(x).__new__(x.__class__)
x = '13';  print type(x).__new__(x.__class__)
x = 1.0j;  print type(x).__new__(x.__class__)
x = True;  print type(x).__new__(x.__class__)
x = (1,2); print type(x).__new__(x.__class__)

然而,以下三个实验给我错误:

x = None;           print type(x).__new__(x.__class__)
x = lambda z: z**2; print type(x).__new__(x.__class__)
x = object;         print type(x).__new__(x.__class__)

错误分别是:

TypeError: object.__new__(NoneType) is not safe, use NoneType.__new__()
TypeError: Required argument 'code' (pos 1) not found
TypeError: type() takes 1 or 3 arguments

为什么这三个例子不起作用? (注意:对于lambda示例,我在调用__new__方法时必须传入代码片段,但我不知道该怎么做。)我使用的是Python 2.6。

请注意,我意识到这不一定是您想要在实际代码中创建新对象的方式,但我的目的不实际,而是要了解低级对象方法的工作原理。

1 个答案:

答案 0 :(得分:14)

它没有什么特别之处,只是对于某些类型,有一个默认的"空"这种类型的对象,而对于其他人则没有。您的工作示例基本上等同于:

int()
dict()
list()
float()
str()
complex()
tuple()

。 。 。所有这些工作。您的最后三个示例基本上是尝试创建NoneType,functiontype的新实例。

  1. NoneType由于一个独特的原因而失败,因为None是一个单例--- NoneType类型只能有一个实例,即None对象。 (您收到的具体错误消息有点奇怪,但如果您执行types.NoneType(),您将收到更直接的消息,说明&#34;无法创建NoneType实例&#34;。)< / LI>
  2. function失败了,因为正如您所见,它需要一个参数,而您却没有提供参数。您需要的是一个代码对象,您可以从现有函数或compile函数获取该代码对象。 (它还需要一个globals参数,这可能只是一个字典。)
  3. type失败,因为您没有给出足够的论据。您可以type(foo)获取foo类型,也可以type(name, bases, dict)创建新类型(即类)。
  4. 请注意,在上一个示例中,您采用的是object类型,它本身就是一种类型。如果改为x = object()(使x成为单个对象而不是对象类型),那么它将起作用并创建一个&#34;空白&#34;对象

    要记住的是,调用__new__并不是那么神奇。当你直接尝试通过someType()实例化类型时会发生什么。如果该类型需要参数,则调用__new__将失败,就像任何其他函数调用将失败一样,如果您没有给它正确的参数,因为type(x).__new__只是一个函数,就像任何其他函数一样。您可以使用用户定义的类来查看它:

    >>> class Foo(object):
    ...     pass
    >>> x = Foo();           print type(x).__new__(x.__class__)
    <__main__.Foo object at 0x00EB0370>
    >>> class Foo(object):
    ...     def __init__(self, someArg):
    ...         pass
    >>> class Foo(object):
    ...     def __new__(cls, someArg):
    ...         return super(Foo, cls).__new__(cls)
    >>> x = Foo(2);           print type(x).__new__(x.__class__)
    Traceback (most recent call last):
      File "<pyshell#32>", line 1, in <module>
        x = Foo(2);           print type(x).__new__(x.__class__)
    TypeError: __new__() takes exactly 2 arguments (1 given)
    

    在第一种情况下成功了,因为我的班级并不需要论证;它在第二个类中失败了,因为第二个类确实需要参数。

    __new__因任何秘密原因不会失败;它只是失败,因为您尝试实例化的类型需要参数才能构造实例。 (None案例是唯一一个不同的案例;由于None是Python中的特殊对象,因此{1}}因特殊原因而失败。