2012-06-07 12 views
12

Grałem około z metaclasses w CPython 3.2.2 i zauważyłem, że jest możliwe, aby skończyć z klasy, która ma swój własny typ:Python - obiekt może być jego własnym typem?

Python 3.2.2 (default, Sep 5 2011, 21:17:14) 
[GCC 4.6.1] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> class MC(type):   #a boring metaclass that works the same as type 
...  pass 
... 
>>> class A(MC, metaclass=MC): #A is now both a subclass and an instance of MC... 
...  pass 
... 
>>> A.__class__ = A   #...and now A is an instance of itself? 
>>> A is type(A) 
True 

Dla naszego metaklasą A, tam naprawdę nie wydają się znacznie od rozróżnienia między klasą i przykład atrybutów:

>>> A.__next__ = lambda self: 1 
>>> next(A) 
1          #special method lookup works correctly 
>>> A.__dict__ 
dict_proxy({'__module__': '__main__', 
'__next__': <function <lambda> at 0x17c9628>, 
'__doc__': None}) 
>>> type(A).__dict__ 
dict_proxy({'__module__': '__main__', 
'__next__': <function <lambda> at 0x17c9628>, 
'__doc__': None})        #they have the same `__dict__` 

Wszystko to działa tak samo (oprócz zmieniających się __metaclass__ i __next__ nie jest specjalna metoda) w CPython 2.7.2, 1.6.0 (pypy który implementuje Python 2.7.1) i Jython 2.2.1 (nie mam pojęcia, co Python wersja, która jest, jeśli w ogóle - nie bardzo znam Jython).

Nie mogę znaleźć wiele wyjaśnień na temat warunków, w których przyznanie __class__ jest dozwolone (najwyraźniej typy te muszą być zdefiniowane przez użytkownika i mają podobny układ w pewnym sensie?). Zauważ, że A musi być zarówno podklasą, jak i instancją MC, aby zadanie zadziałało na __class__. Czy tak naprawdę rekurencyjne hierarchie metaklasu powinny być akceptowalne? Jestem bardzo zmieszany.

+1

Dokument, który dużo wyjaśnia o typach Pythona, jest następujący: http://www.cafepy.com/article/python_types_and_objects/python_types_and_objects.html Powinien to wyjaśnić, choć wydaje się, że nie omawia tej sytuacji. –

Odpowiedz

6

rekurencyjne hierachies metaklasa są właściwie częścią rdzenia języka:

>>> type(type) 
<class 'type'> 

więc nawet średnia metaklasa type jest jego własny rodzaj. Nie ma żadnego konceptualnego problemu z tym konstruktem - to po prostu oznacza atrybut __class__ wskazuje na samą klasę.

Przypisania do atrybutu __class__ są dozwolone tylko dla klas zdefiniowanych przez użytkownika. Przypisanie jest legalne, jeśli zarówno pierwotna klasa, jak i nowa klasa nie definiują __slots__ lub obydwu zestawów __slots__ dla tej samej sekwencji.

Powiązane problemy