2012-09-30 5 views
13

Pythonのデータモデルについて学ぶにあたり、私は__new__メソッドを使って既存のオブジェクトからオブジェクトを作成しています。ここでは、様々なタイプの新しいオブジェクトを作成するいくつかの例は以下のとおりです。__new__を使った既存のオブジェクトからのPythonオブジェクト

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

ただし、以下の3つの実験は私にエラーを与える:

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 

なぜこれらの3つの例は機能しませんか? (注:lambdaの例では、__new__メソッドを呼び出すとコードフラグメントを渡す必要がありますが、その方法はわかりません)。私はPython 2.6を使用しています。

これは必ずしも実際のコードで新しいオブジェクトを作成したいとは限りませんが、私の目的は実用的ではなく、むしろ低レベルのオブジェクトメソッドの仕組みを理解することです。

+1

そして、正確にはエラーメッセージが表示されます。 –

+0

メッセージが追加されました、Rohit。提案していただきありがとうございます。 – rlandster

答えて

14

これは特別なものではありません。一部のタイプの場合、そのタイプのデフォルトの「空の」オブジェクトがありますが、他のタイプのオブジェクトはありません。実際の作業例は、基本的には次のようになります。

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

。 。すべてがうまくいく。最後の3つの例は、基本的に、NoneType、function、およびtypeの新しいインスタンスを作成しようとしています。

  1. Noneはシングルトンであるため、NoneTypeはユニークな理由で失敗します.LongType型は1つのインスタンス、つまりNoneオブジェクトしか持てません。 (具体的なエラーメッセージは少し奇妙ですが、types.NoneType()を実行すると、「タイプのインスタンスを作成できません」というより直接的なメッセージが表示されます)。
  2. functionは、あなたはそれを提供しません。あなたが必要とするのは、既存の関数またはcompile関数から得ることができるコードオブジェクトです。 (globals引数も必要ですが、これは単なるdictでもかまいません)。
  3. typeは十分な引数がないため失敗します。 fooの型を取得するにはtype(foo)を、新しい型(つまりクラス)を作成するにはtype(name, bases, dict)を実行します。

あなたの最後の例では、それ自体がタイプのobjectを使用していることに注意してください。 x = object()を代わりに実行すると(xをオブジェクトタイプではなく個々のオブジェクトにする)、それは動作して "空の"オブジェクトを作成します。

覚えておくべきことは、__new__を呼び出すことは本当に魔法ではないということです。 someType()を実行して直接型をインスタンス化しようとすると、どうなるでしょうか。その型に引数が必要な場合は、type(x).__new__は他の関数と同様の関数なので、他の関数呼び出しが失敗した場合と同様に、__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) 

私のクラスは引数を必要としなかったので、最初のケースで成功しました。 2番目のクラスは引数を必要とするため、2番目のクラスで失敗しました。

__new__は、何らかの理由で失敗しません。インスタンス化しようとしている型はインスタンスを構築するために引数を必要とするため、失敗します。 Noneは特殊な理由から失敗します。NoneはPythonの特別なオブジェクトです。

+0

非常に明確に+1された+1 – JamesSwift

関連する問題