Питонический способ доступа к атрибуту класса внутри класса
Мне было интересно, как вы думаете, как получить доступ к атрибуту класса из функции в классе. Я не нашел ссылки на 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
только печет в некоторой хрупкости, которую может быть трудно обнаружить в будущем.