Подтвердить что ты не робот

Доступ к переменной класса из экземпляра

У меня есть этот класс:

class ReallyLongClassName:

    static_var = 5

    def instance_method(self):
        ReallyLongClassName.static_var += 1

Есть ли способ получить доступ к статической переменной, используя переменную self? Я бы предпочел сделать что-то вроде class(self).static_var += 1, потому что длинные имена нечитаемы.

4b9b3361

Ответ 1

Используйте self.__class__.classAttr. Это должно работать как для старых, так и для новых классов стиля.

Ответ 2

Ответ: "да, но..."

Лучший способ понять - попробовать на самом деле:

>>> class RLCN:
...     static_var = 5
...     def method1(self):
...         RLCN.static_var += 1
...     def method2(self):
...         self.static_var += 1
>>> rlcn = RLCN()
>>> RLCN.static_var, rlcn.static_var
(5, 5)
>>> rlcn.static_var
5
>>> rlcn.method1()
>>> RLCN.static_var, rlcn.static_var
(6, 6)
>>> rlcn.method2()
>>> RLCN.static_var, rlcn.static_var
(6, 7)

Что случилось?

Ну, доступ к атрибуту класса через self работает просто отлично. Если атрибут экземпляра с тем же именем отсутствует, вы получаете атрибут class.

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

Обратите внимание, что это означает, что атрибуты класса можно использовать атрибуты класса как "значения по умолчанию" или "начальные значения" для атрибутов экземпляра. Но я не уверен, что это очень Pythonic. что происходит на самом деле, и то, что думает начинающий (особенно кто-то, например, С++ 11 или Java), очень разные.

(Вещи немного сложнее, когда вы имеете дело с дескрипторами, например методами или @property s, но не обращайте на них внимания, в простом случае, который вы обсуждаете, это не имеет значения.)


Я бы предпочел сделать что-то вроде класса (self).static_var + = 1, потому что длинные имена нечитаемы.

Вы можете, вам просто нужно правильно записать: type - это функция, возвращающая тип любого объекта. Итак:

type(self).static_var += 1

Это имеет дополнительное преимущество: быть динамичным (например, когда вы имеете множественное наследование и не знаете, с какой стороны появляется @property, вы, вероятно, не хотите явно указывать имя класса, в основном для того же Причина, по которой вы хотите использовать super() вместо явного вызова метода базового класса).

Недостаток заключается в том, что вы не работаете над классами старого стиля в Python 2.x, но тогда вы не должны их использовать. Особенно в классах, которые нуждаются в атрибутах класса, потому что это те типы, которые вы часто захотите добавить @classmethod s, @property s и т.д., И ни одно из них не работает со старым стилем классов (наряду со многими другими вещами). Если по какой-то причине вам действительно нужно обрабатывать классы старого стиля и нового стиля, self.__class__ работает со старыми классами. Я не уверен, что он гарантирует работу с классами нового стиля; Документы говорят, что возвращаемое значение type(object) является "обычно тем же самым объектом, что и возвращаемый object.__class__", но не говорит, при каких условиях "вообще" неверно. Он также задокументирован как специальный атрибут добавленный реализацией для нескольких типов объектов в 3.x. На практике я не знаю ни одного случая, когда они различаются в 3.x, а в 2.x наиболее заметным случаем, когда они отличаются, являются классы старого стиля.