Питонический способ доступа к атрибуту класса внутри класса

Мне было интересно, как вы думаете, как получить доступ к атрибуту класса из функции в классе. Я не нашел ссылки на PEP8 или популярного вопроса по этому поводу. например

class MyClass(object):
    BAR = 1
    def foo(self):
        # Way A:
        print(self.BAR)

        # Way B:
        print(MyClass.BAR)

Доступ через "я" кажется разумным, поскольку атрибут принадлежит одному и тому же классу, близкая ссылка для очевидной ссылки того же класса. С другой стороны, доступ через само имя класса является понятным, поскольку он является статическим и делает происхождение использования понятным, а также может быть более понятным, поскольку он связан с именем класса.

2 ответа

При явном названии имени класса вы не допускаете, чтобы подкласс переопределял ваш атрибут.

С другой стороны, использование self дает вам эту гибкость. Рассмотрим следующий код:

class MyClass(object):
    BAR = 1
    def foo(self):
        # Way A:
        print(self.BAR)

        # Way B:
        print(MyClass.BAR)


class SubClass(MyClass):
    BAR = 2

class SubClass2(MyClass):
    pass

# output
>>> a = SubClass()
>>> a.foo()
2
1
>>> b = SubClass2()
>>> b.foo()
1
1

Для чтения не имеет значения, какой вы используете - self.BAR а также MyClass.BAR синтаксически эквивалентны, если у вас нет иерархии классов, где подкласс переопределяет значение BAR,

Для записи они не одинаковы. Запись в self.BAR будет эффективно создавать новую переменную, которая является локальной для self экземпляр объекта, поэтому любой читает из self.BAR из другого экземпляра объекта не увидит изменений. Это может быть довольно ужасно для отладки, потому что из кода не очевидно, что должно произойти, так как он чувствителен ко времени.

В общем случае для переменных класса вы действительно должны использовать MyClass.BAR если вы хотите конкретную переменную из определенного уровня в иерархии классов, или type(self).BAR или же self.__class__.BAR если вы хотите что-то, что является безопасным наследством. Это определенно и очевидно переменная класса, позволяющая избежать проблемы, описанной выше, с появлением динамических псевдонимов во время выполнения. С помощью self только печет в некоторой хрупкости, которую может быть трудно обнаружить в будущем.

Другие вопросы по тегам