Python: вложенный класс со статическим методом не работает

Что не так в следующем коде?

class A:
    def A_M(self): pass
    class B:
        @staticmethod
        def C(): super(B).A_M()

ошибка (Питон 2.7.3):

>>> a = A()
>>> a.B.C()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "..x.py", line 36, in C
    def C(): super(B).A_M()
NameError: global name 'B' is not defined

Изменить:
решение было простым:

class A:
    def A_M(self): pass
    class B:
        @staticmethod
        def C(): A().A_M()                 #use of A() instead of supper, etc.

Важное примечание: с этим решением связана проблема. Если вы измените имя суперкласса (например, A), вам придется обновить все виды использования внутри себя как A :)).


person Developer    schedule 25.04.2013    source источник
comment
Почему вы думаете, что вам нужен вложенный класс? Практически нет причин иметь это в Python.   -  person Daniel Roseman    schedule 25.04.2013
comment
Если вы измените имя суперкласса (т.е. A), вам придется обновить все виды использования внутри себя как A - Это не то, что означает суперкласс   -  person Eric    schedule 26.04.2013


Ответы (3)


class A(object):
    def foo(self):
        print('foo')

    @staticmethod
    def bar():
        print('bar')

    class B(object):
        @staticmethod
        def bar(obj):
            # A.foo is not staticmethod, you can't use A.foo(),
            # you need an instance.
            # You also can't use super here to get A,
            # because B is not subclass of A.
            obj.foo()
            A.foo(obj)  # the same as obj.foo()

            # A.bar is static, you can use it without an object.
            A.bar()

class B(A):
    def foo(self):
        # Again, B.foo shouldn't be a staticmethod, because A.foo isn't.
        super(B, self).foo()

    @staticmethod
    def bar():
        # You have to use super(type, type) if you don't have an instance.
        super(B, B).bar()


a, b = A(), B()

a.B.bar(a)
b.foo()
B.bar()

Подробнее о super(B, B) см. здесь.

person gatto    schedule 25.04.2013
comment
поэтому решение таково: class A: def A_M(self): pass class B: @staticmethod def C(): A().A_M() - person Developer; 25.04.2013

Вы должны использовать полное имя. Кроме того, в python 2.7 вам нужно использовать (object), иначе super(A.B) даст TypeError: must be type, not classobj

class A(object):
    def A_M(self):
        pass

    class B(object):
        @staticmethod
        def C():
            super(A.B).A_M()

Наконец, super(A.B) здесь по существу object. Вы имели в виду, что B наследуется от A? Или вы просто искали A.A_M()?

person Eric    schedule 25.04.2013
comment
не работает: ... ошибка: def C(): super(A.B).A_M() TypeError: must be type, not classobj - person Developer; 25.04.2013
comment
@Разработчик: Хорошо, теперь прочитайте мой пост еще раз: Кроме того, в python 2.7 вам нужно использовать (объект). super работает только с классами нового стиля - person Eric; 25.04.2013
comment
все еще не работает: ...ошибка: super(A.B).A_M() AttributeError: 'super' object has no attribute 'A_M' - person Developer; 25.04.2013
comment
@Разработчик: Продолжайте читать - super(A.B) по сути object здесь. И object.A_M() не существует. Вы имели в виду, что B наследует от A? Или вы просто искали A.A_M()? - person Eric; 25.04.2013
comment
Даже если он был унаследован, он все равно не думает, что он будет работать, потому что он статичен. - person GP89; 25.04.2013
comment
@ Эрик Просто A.A_M(). B не наследуется от A, а инкапсулируется внутри него. - person Developer; 25.04.2013

Опоздавший, чтобы просто инкапсулировать B в A, это простой способ:

class A:
    def A_M(self):
        return "hi"

    class B:
        @staticmethod
        def C():
            return A().A_M()

a = A()
print a.B().C()

Не уверен, что это то, что вам нужно, но вопрос все еще оставался нерешенным, поэтому я догадался.

person JHolta    schedule 25.04.2013
comment
a.B().C() неверно. a.B.C() правильно (потому что C статично в B). Я проголосовал за ваш ответ, кстати. Ответ gatto говорит то же самое, но немного длинно. - person Developer; 25.04.2013