Достижение фиксированной точки «типа»

#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 самого себя или одного из его подтипов.