Python - ссылочный внутренний класс из другого внутреннего класса

Я пытаюсь ссылаться на внутренний класс из другого внутреннего класса. Я пробовал оба:

class Foo(object):

  class A(object):
    pass

  class B(object):
    other = A

а также

class Foo(object):

  class A(object):
    pass

  class B(object):
    other = Foo.A

с соответствующими результатами:

Traceback (most recent call last):
  File "python", line 1, in <module>
  File "python", line 6, in Foo
  File "python", line 7, in B
NameError: name 'A' is not defined

а также

Traceback (most recent call last):
  File "python", line 1, in <module>
  File "python", line 6, in Foo
  File "python", line 7, in B
NameError: name 'Foo' is not defined

Это возможно?

3 ответа

Решение

Это невозможно, поскольку все, что вы определяете в классе, становится действительным членом только в экземпляре этого класса, если только вы не определили метод с @staticmethod, но нет такого свойства для класса.

Так что это тоже не сработает:

class Foo(object):
    x = 10

    class A(object):
        pass

    class B(object):
        other = x

Это будет работать, но это не то, что вы хотели:

class Foo(object):
  x = 10

  class A(object):
    pass

  class B(object):
    def __init__(self):
        self.other = Foo.A

f = Foo()
print(f.B().other)

Выход:

<class '__main__.Foo.A'>

Причина, по которой это работает, заключается в том, что методы (в данном случае __init__) оцениваются при создании объекта, в то время как __init__ оцениваются, пока класс читается и интерпретируется.

Вы можете получить примерно то же, что и вы, просто определив все классы внутри собственного модуля. Импортируя модуль, он становится объектом, поля которого являются классами, которые вы в нем определяете.

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

      class Class2:

    class Labels:
        c2l1 = 'label 1'
        c2l2 = 'label 2' 

    class Params:
        pass 
        # p1 = None
        # p2 = None
        # p3 = None

    Params.p1 = Labels.c2l2
    Params.p2 = 1234


print(Class2.Params.p1)
print(Class2.Params.p2)
# print(Class2.Params.p3)

      label 2
1234

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

Другим решением здесь является превращение Foo в модуль и уменьшение кода.

Или можно сделать это, определив класс B с помощью функции типа. Это использует локальную область видимости Foo.

      class Foo(object):

  class A(object):
    pass

  B = type('B', (object,), {'other': A})


print(Foo.A)
print(Foo.B)
print(Foo.B.other)

Распечатывает:

      <class '__main__.Foo.A'>
<class '__main__.B'>
<class '__main__.Foo.A'>
Другие вопросы по тегам