2012-09-30 11 views
13

Beim Lernen über Python-Datenmodell, spiele ich mit dem Erstellen von Objekten aus vorhandenen Objekten mit der Methode __new__. Hier sind einige Beispiele, die neuen Objekte verschiedenen Typen erstellen:Python-Objekte aus vorhandenen Objekten mit __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__) 

jedoch die folgenden drei Versuche geben Sie mir Fehler:

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__) 

Die Fehler sind (jeweils):

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 

Warum funktionieren diese drei Beispiele nicht? (Hinweis: für das lambda Beispiel scheint es, dass ich ein Codefragment übergeben muss, wenn ich die __new__ Methode aufrufen, aber ich weiß nicht, wie das geht.) Ich verwende Python 2.6.

Bitte beachten Sie, dass ich weiß, dass dies nicht unbedingt die Art und Weise ist, wie Sie neue Objekte in echtem Code erstellen möchten, aber mein Zweck ist nicht praktikabel, sondern zu verstehen, wie die Low-Level-Objektmethoden funktionieren.

+1

Und was genau Fehler sagt, wird es für uns vorteilhaft sein .. –

+0

Nachrichten hinzugefügt , Rohit. Danke für den Vorschlag. – rlandster

Antwort

14

Es ist nichts besonderes, es ist nur, dass für einige Typen ein "leeres" Standardobjekt dieses Typs vorhanden ist, während es für andere nicht ist. Ihre Arbeitsbeispiele sind grundsätzlich äquivalent zu:

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

. . . die alle funktionieren. Ihre letzten drei Beispiele versuchen im Grunde, neue Instanzen von NoneType, function, und type zu erstellen.

  1. NoneType schlägt aus einem bestimmten Grund fehl, weil None ein Singleton ist - der NoneType-Typ kann immer nur eine Instanz haben, nämlich das None-Objekt. (Die spezifische Fehlermeldung, die Sie erhalten, ist ein wenig seltsam, aber wenn Sie types.NoneType() tun, erhalten Sie eine direktere Nachricht mit der Aufschrift "Kann keine NoneType-Instanzen erstellen".)
  2. function schlägt fehl, weil, wie Sie gesehen haben, es erfordert Argument, und Sie bieten keine an. Was Sie benötigen, ist ein Code-Objekt, das Sie von einer bestehenden Funktion oder von der compile Funktion erhalten könnten. (Es erfordert auch ein globals Argument, das kann nur ein Diktat sein.)
  3. type schlägt fehl, weil Sie nicht genug Argumente geben. Sie können entweder type(foo) ausführen, um den Typ von foo zu erhalten, oder type(name, bases, dict), um einen neuen Typ (d. H. Eine Klasse) zu erstellen.

Beachten Sie übrigens, dass Sie in Ihrem letzten Beispiel den Typ object nehmen, der selbst ein Typ ist. Wenn Sie stattdessen x = object() tun (wodurch x ein individuelles Objekt und nicht der Objekttyp ist), wird es funktionieren und ein "leeres" Objekt erstellen.

Die Sache zu erinnern ist, dass das Anrufen __new__ nicht wirklich magisch ist. Es ist genau das, was passiert, wenn Sie versuchen, den Typ zu instanziieren, indem Sie someType() tun. Wenn dieser Typ Argumente benötigt, schlägt der Aufruf von __new__ fehl, genau wie jeder andere Funktionsaufruf, wenn Sie ihm nicht die richtigen Argumente geben, weil type(x).__new__ nur eine Funktion wie jede andere Funktion ist.Sie können dies mit einer benutzerdefinierten Klasse anzeigen:

>>> 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) 

Es gelang im ersten Fall, weil meine Klasse keine Argumente benötigt; Es ist in der zweiten Klasse fehlgeschlagen, da die zweite Klasse Argumente benötigt.

Die __new__ schlägt aus irgendeinem geheimen Grund nicht fehl; Es schlägt nur fehl, da der Typ, den Sie zu instanziieren versuchen, Argumente benötigt, um eine Instanz zu erstellen. (Der None Fall ist der einzige, der hier anders ist; dieser scheitert aus einem besonderen Grund, weil None ein spezielles Objekt in Python ist.)

+0

Sehr klar erklärt +1 – JamesSwift