Pytanie Python - obiekt może być własnym typem?


Grałem z metaclasses w CPython 3.2.2, i zauważyłem, że możliwe jest, aby skończyć z klasą, która jest 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 metaklasu A, tak naprawdę nie ma większego rozróżnienia między atrybutami klasy i instancji:

>>> 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 zmiany na __metaclass__, i __next__ nie będąc specjalną metodą) w CPython 2.7.2, PyPy 1.6.0 (który implementuje Python 2.7.1) i Jython 2.2.1 (nie mam pojęcia, która wersja Pythona jest, jeśli w ogóle - nie bardzo znam Jythona ).

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


12
2018-06-07 16:41


pochodzenie


Dokument wyjaśniający wiele typów Pythona jest następujący: cafepy.com/article/python_types_and_objects/... Powinno to wyjaśnić, choć wydaje się, że nie omawia tej sytuacji. - Simeon Visser


Odpowiedzi:


Rekurencyjne hierachie metaklasy są w rzeczywistości częścią jądra językowego:

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

Więc nawet standardowy metaclass type jest jego własnym typem. Nie ma konceptualnego problemu z tym konstruktem - po prostu oznacza to __class__ atrybut klasy wskazuje na samą klasę.

Przydziały do __class__ atrybut jest dozwolony tylko dla klas zdefiniowanych przez użytkownika. Przypisanie jest legalne, jeśli nie zdefiniowano ani oryginalnej, ani nowej klasy __slots__lub oba zestawy __slots__ do tej samej sekwencji.


6
2018-06-07 21:01