#python #python-3.x #types
#python #python-3.x #типы
Вопрос:
Вызов type(x)
объекта x
возвращает тип этого объекта. Вызов type(type(...type(x)...))
всегда в конечном итоге приводит type
к самому себе, type(type) = type
являясь фиксированной точкой. Самый сложный пример, который я мог придумать, был
class Meta(type):
pass
class C(metaclass=Meta):
pass
x = C()
для чего требуется три вызова type ( type(type(type(x)))
) для вычисления type
.
Верно ли для любого выражения в Python, что для достижения фиксированной точки требуется не более трех вызовов type
? Если нет, существует ли конечный предел (чуть больше трех) или требуемый стек type
вызовов может расти бесконечно?
Комментарии:
1. Обратите внимание, что в вашем примере,
isinstance(Meta, type)
или другими словамиtype(C) <: type
. Требование дополнительногоtype
слоя связано просто с игнорированием подтипов. Однакоtype(type) == type
это базовый вариант, из которого может быть получено произвольное множество дополнительных уровней.
Ответ №1:
Требуемый стек type
вызовов может расти бесконечно.
Вот пример:
>>> class Meta(type):
... pass
...
>>> class C(type, metaclass=Meta):
... pass
...
>>> class D(type, metaclass=C):
... pass
...
>>> class E(type, metaclass=D):
... pass
...
>>> class F(type, metaclass=E):
... pass
...
>>> f = F("1",(),{});
>>> type(f)
<class '__main__.F'>
>>> type(type(f))
<class '__main__.E'>
>>> type(type(type(f)))
<class '__main__.D'>
>>> type(type(type(type(f))))
<class '__main__.C'>
>>> type(type(type(type(type(f)))))
<class '__main__.Meta'>
>>> type(type(type(type(type(type(f))))))
<class 'type'>
>>> type(type(type(type(type(type(type(f)))))))
<class 'type'>
>>>
Комментарии:
1. поправьте меня, если я ошибаюсь, но я думаю, что все объекты хранятся в куче, а указатель на сам объект хранится в стеке
2. куча используется при переполнении стека для локальных переменных, которые сильно изменяются, как i в циклах; стек используется для глобальных данных и возвратов функций, типичной ошибкой сегментации в c является переполнение стека или доступ к недопустимым местоположениям
Ответ №2:
Случай type(type) == type
является просто базовым случаем инстанцируемых типов. Так же, как может быть создан первый слой типов, могут быть созданы type
дополнительные слои. Фиксированного предела нет.
def descend(base=type):
while True:
class base(base, metaclass=base):
pass
yield base
def type_depth(tp):
depth = 0
while type(tp) != type:
depth = 1
tp = type(tp)
return depth
for tp in descend():
print(tp, type_depth(tp))
Практически, существует предел полезности мета-слоев: большинство классов являются прямыми экземплярами type
самого себя или одного из его подтипов.