15

在学习 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。

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

4

1 回答 1

15

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

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

. . . 所有这些都有效。您的最后三个示例基本上是尝试创建 NoneType、function和的新实例type

  1. NoneType 由于一个独特的原因而失败,因为 None 是一个单例 --- NoneType 类型只能有一个实例,即 None 对象。(您收到的具体错误消息有点奇怪,但如果您这样做,types.NoneType()您会收到一条更直接的消息,说“无法创建 NoneType 实例”。)
  2. function失败是因为,如您所见,它需要一个参数,而您没有提供一个参数。您需要的是一个代码对象,您可以从现有函数或compile函数中获取它。(它还需要一个globals参数,它可以只是一个字典。)
  3. type失败是因为你没有给出足够的论据。您可以type(foo)获取 foo 的类型,也type(name, bases, dict)可以创建新类型(即类)。

请注意,在上一个示例中,您使用的类型是object,它本身就是一种类型。如果您这样做x = object()(使 x 成为单个对象而不是对象类型),那么它将起作用并创建一个“空白”对象。

要记住的是,召唤__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 中的一个特殊对象。)

于 2012-09-30T05:32:49.510 回答