Атрибуты класса в Python

Есть ли разница в следующих двух частях кода? Если нет, то предпочтительнее ли одно другому? Почему нам разрешено создавать атрибуты класса динамически?

Фрагмент 1

class Test(object):
    def setClassAttribute(self):
        Test.classAttribute = "Class Attribute"

Test().setClassAttribute()

Фрагмент 2

class Test(object):
    classAttribute = "Class Attribute"

Test()

3 ответа

Решение

Более естественно сделать это как #2, но обратите внимание, что они делают разные вещи. С # 2 у класса всегда есть атрибут. С #1 у него не будет атрибута, пока вы не позвоните setClassAttribute,

Вы спросили: "Почему нам разрешено создавать атрибуты класса динамически?" В случае с Python часто возникает вопрос не "почему нам это разрешено", а "почему нас должны предотвращать"? Класс - это объект, как и любой другой, он имеет атрибуты. Объекты (как правило) могут получить новые атрибуты в любое время. Нет причин делать из класса исключение из этого правила.

Во-первых, установка атрибута класса в методе экземпляра - странная вещь. И игнорируя self параметр и идти прямо к Test это еще одна странная вещь, если вы не хотите, чтобы все подклассы разделяли одно значение. *

* Если бы вы специально хотели, чтобы все подклассы разделяли одно значение, я бы сделал это @staticmethod без параметров (и установите его на Test ). Но в этом случае он даже не используется в качестве атрибута класса и может работать лучше как глобальный модуль со свободной функцией для его установки.

Итак, даже если вы захотите перейти с первой версией, я напишу это так:

class Test(object):
    @classmethod
    def setClassAttribute(cls):
        cls.classAttribute = "Class Attribute"

Test.setClassAttribute()

Однако, несмотря на все сказанное, я думаю, что второе гораздо более питонное. Вот соображения:

  • В общем, геттеры и сеттеры настоятельно не рекомендуются в Python.
  • Первый оставляет пробел, в течение которого класс существует, но не имеет атрибута.
  • Простое лучше, чем сложное.

Единственное, что нужно иметь в виду, это то, что одна из причин, по которой геттеры и сеттеры не нужны в Python, заключается в том, что вы всегда можете заменить атрибут на @property если позже вам понадобится его вычислить, проверить и т. д. С атрибутом class это не совсем идеальное решение, но обычно оно достаточно хорошее.


И последнее: атрибуты класса (и методы класса, за исключением альтернативного конструктора) часто являются признаком непитонического дизайна на более высоком уровне. Конечно, не всегда, но достаточно часто, так что стоит объяснить вслух, почему вы думаете, что вам нужен атрибут класса и убедиться, что он имеет смысл. (И если вы когда-либо программировали на языке, чьи идиомы широко используют атрибуты класса, особенно если это Java, найдите того, кто никогда не использовал Java, и попытайтесь объяснить это ему.)

Я думаю, что #2 кажется более естественным. Реализация #1 означает, что атрибут не устанавливается до тех пор, пока не будет создан фактический экземпляр класса, что мне кажется противоречащим тому, каким должен быть атрибут класса (против атрибута объекта).

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