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

ただし、次の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__方法がわかりません。)Python2.6を使用しています。

これは必ずしも実際のコードで新しいオブジェクトを作成する方法ではないことに注意してください。しかし、私の目的は実用的ではなく、低レベルのオブジェクトメソッドがどのように機能するかを理解することです。

4

1 に答える 1

15

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

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

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

  1. Noneはシングルトンであるため、NoneTypeは固有の理由で失敗します--- NoneTypeタイプは、1つのインスタンス、つまりNoneオブジェクトしか持つことができません。(表示される特定のエラーメッセージは少し奇妙ですが、types.NoneType()表示すると、「NoneTypeインスタンスを作成できません」というより直接的なメッセージが表示されます。)
  2. functionご覧のとおり、引数が必要であり、引数を指定しないため、失敗します。必要なのは、既存の関数または関数から取得できるコードオブジェクトですcompile。(また、globals引数が必要ですが、これは単なる口述になる可能性があります。)
  3. type十分な引数を与えなかったために失敗します。type(foo)fooのタイプを取得するかtype(name, bases, dict)、新しいタイプ(つまり、クラス)を作成するために行うことができます。

objectちなみに、最後の例では、それ自体がタイプであるタイプを使用していることに注意してください。代わりに(xをx = object()オブジェクトタイプではなく個別のオブジェクトにする)すると、それは機能し、「空白の」オブジェクトを作成します。

覚えておくべきことは、呼び出し__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)

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

秘密の__new__理由で失敗することはありません。インスタンス化しようとしている型がインスタンスを構築するために引数を必要とするため、失敗するだけです。(ここで異なるのはケースだけです。Pythonの特別なオブジェクトであるNoneため、特別な理由で失敗します。)None

于 2012-09-30T05:32:49.510 に答える