【问题标题】:Python objects from existing objects using __new__使用 __new__ 来自现有对象的 Python 对象
【发布时间】:2012-09-21 10:46:50
【问题描述】:

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

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

【问题讨论】:

  • 究竟是什么错误说这对我们有益..
  • 添加了消息,Rohit。感谢您的建议。

标签: python object types instantiation


【解决方案1】:

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

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

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

  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 中的特殊对象。)

【讨论】:

    猜你喜欢
    • 2020-10-27
    • 1970-01-01
    • 1970-01-01
    • 2018-09-16
    • 2019-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-19
    相关资源
    最近更新 更多