Python: определите, вкладывается ли класс

В моем случае: убедитесь, что ваш файл содержит хотя бы один класс перед компиляцией!

6
задан Paolo Tedesco 24 March 2009 в 10:33
поделиться

5 ответов

AFAIK, учитывая класс и никакую другую информацию, Вы не можете сказать, является ли это вложенным классом. Однако посмотрите здесь для того, как Вы могли бы использовать декоратора для определения этого.

Проблема состоит в том, что вложенный класс является просто нормальным классом, это - атрибут его внешнего класса. Другие решения, что Вы могли бы ожидать работать, вероятно, не будут- inspect.getmro, например, только дает Вам базовые классы, не внешние классы.

Кроме того, вложенные классы редко необходимы. Я сильно пересмотрел бы, является ли это хорошим подходом в каждом особом случае, где Вы чувствуете себя заставленными использовать тот.

13
ответ дан 8 December 2019 в 05:23
поделиться

Внутренний класс не предлагает конкретных специальных функций в Python. Это - только свойство объекта класса, не отличающегося от целочисленного или свойства строки. Ваш пример OuterClass/InnerClass может быть переписан точно как:

class OuterClass(): pass
class InnerClass(): pass
OuterClass.InnerClass= InnerClass

InnerClass не может знать, был ли он объявлен в другом классе, потому что это - просто простая привязка переменной. Волшебство, которое заставляет связанные методы знать о своем владельце 'сам', не применяется здесь.

innerclass волшебство декоратора в ссылке, которую отправил John, является интересным подходом, но я не использовал бы его как есть. Это не кэширует классы, которые это создает для каждого внешнего объекта, таким образом, Вы получаете новый InnerClass каждый раз, когда Вы называете outerinstance. InnerClass:

>>> o= OuterClass()
>>> i= o.InnerClass()
>>> isinstance(i, o.InnerClass)
False # huh?
>>> o.InnerClass is o.InnerClass
False # oh, whoops...

Также способ, которым это пытается копировать поведение Java предоставления доступа к внешним переменным класса, на внутреннем классе с getattr/setattr, является очень изворотливым, и ненужным действительно (так как больше Pythonic путь должно было бы звонить i. __ внешний __. attr явно).

5
ответ дан 8 December 2019 в 05:23
поделиться

Если Вы не устанавливаете его сами, я не полагаю, что существует любой способ определить, вкладывается ли класс. Так же так или иначе класс Python не может использоваться как пространство имен (или по крайней мере не легко), я сказал бы, что лучшая вещь сделать просто использовать различные файлы.

0
ответ дан 8 December 2019 в 05:23
поделиться

Действительно вложенный класс не отличается от любого другого класса - это просто, оказывается, определяется где-то в другом месте, чем пространство имен верхнего уровня (в другом классе вместо этого). Если мы изменяем описание от "вложенного" до "неверхнего уровня", то Вы можете почти достичь достаточно к тому, в чем Вы нуждаетесь.

например:

import inspect

def not_toplevel(cls):
    m = inspect.getmodule(cls)
    return not (getattr(m, cls.__name__, []) is cls)

Это будет работать на общие падежи, но это не может сделать то, что Вы хотите в ситуациях, где классы переименовываются или иначе управляются после определения. Например:

class C:             # not_toplevel(C) = False
    class B: pass    # not_toplevel(C.B) = True

B=C.B                # not_toplevel(B) = True

D=C                  # D is defined at the top, but...
del C                # not_toplevel(D) = True

def getclass():      # not_toplevel(getclass()) = True
    class C: pass
4
ответ дан 8 December 2019 в 05:23
поделиться

Спасибо всем за Ваши ответы.
Я нашел это возможное решение с помощью метаклассов; я сделал это больше для obstination, чем реальная потребность, и это сделано способом, который не будет применим к python 3.
Я хочу совместно использовать это решение так или иначе, таким образом, я отправляю его здесь.

#!/usr/bin/env python
class ScopeInfo(type): # stores scope information
    __outers={} # outer classes
    def __init__(cls, name, bases, dict):
        super(ScopeInfo, cls).__init__(name, bases, dict)
        ScopeInfo.__outers[cls] = None
        for v in dict.values(): # iterate objects in the class's dictionary
            for t in ScopeInfo.__outers:
                if (v == t): # is the object an already registered type?
                    ScopeInfo.__outers[t] = cls
                    break;
    def FullyQualifiedName(cls):
        c = ScopeInfo.__outers[cls]
        if c is None:
            return "%s::%s" % (cls.__module__,cls.__name__)
        else:
            return "%s.%s" % (c.FullyQualifiedName(),cls.__name__)

__metaclass__ = ScopeInfo

class Outer:
    class Inner:
        class EvenMoreInner:
            pass

print Outer.FullyQualifiedName()
print Outer.Inner.FullyQualifiedName()
print Outer.Inner.EvenMoreInner.FullyQualifiedName()
X = Outer.Inner
del Outer.Inner
print X.FullyQualifiedName()
1
ответ дан 8 December 2019 в 05:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: