Динамически осуждается добавление атрибутов в Python? - PullRequest
4 голосов
/ 28 октября 2011

В Python вы можете назначить произвольный атрибут вне определяющего класса :

class Profile(models.Model):
    user = models.OneToOneField(User)  
    name = models.CharField(max_length=140)

p = Profile()
p.age = 42

Основным механизмом здесь является атрибут __dict__, который содержит словарь всех атрибутов.

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


Что я имею в виду ...

Каждое Tweet имеет стандартные поля, такие как id, text, owner.
Возвращая список твитов для пользователя, вы хотите отобразить, является ли твит «избранным» этим пользователем.

Очевидно, что для получения is_favorite вам нужно запросить отношение «многие ко многим» для этого user.
Хорошо ли было бы предварительно заполнить Tweet объекты is_favorite, соответствующими текущему пользователю ?

Конечно, я могу представить метод is_favorite_for(user), но я бью Язык шаблонов Django Ограничения, которые не позволяют вызывать методы с аргументами изнутри шаблона. Кроме того, я считаю, шаблон не должен вызывать методы вообще .


Я знаю, что это будет работать нормально, но мне интересно, если бы подобное в проекте с открытым исходным кодом заставило бы других разработчиков смотреть на меня с презрением.

Sidenote:

Я пришел из C # / .NET, где динамические типы были введены совсем недавно и не получили широкого применения, за исключением некоторых нишевых областей (совместимость, платформы IoC, клиентские платформы REST и т. Д.).

Ответы [ 3 ]

6 голосов
/ 28 октября 2011

Я считаю, что это плохая практика.

Объект не знает, что вы играете с его атрибутами. Например, рассмотрим, что произойдет, если Profile позднее будет расширен, чтобы иметь атрибут age, не связанный с p.age в вашем коде.

Если вы хотите добавить атрибуты, почему бы не создать подкласс Profile или иметь внешнее сопоставление Profiles для объекта с вашими пользовательскими атрибутами?

3 голосов
/ 28 октября 2011

Я думаю, что ответ: это зависит.Во-первых, если вы действительно хотите предотвратить это, вы можете определить __slots__ в классе.И, как правило, не рекомендуется добавлять атрибуты, которые на самом деле не определены в классе, так как это может сбить с толку того, кто читает код, и редко бывает полезно.для этого и в документации Python обсуждается это как способ получить нечто похожее на структуру C или запись Pascal (см. http://docs.python.org/tutorial/classes.html в разделе 9.7 «Шансы и конец»).

2 голосов
/ 28 октября 2011

Если атрибут присутствует только иногда, вы рискуете получить AttributeError из ниоткуда для одного объекта, в то время как код работал нормально для другого объекта того же класса (да, точные типы не так важны при типизированной утилитой), но объекты одного и того же класса часто считаются одними и теми же «типами утки»).Даже если этого не произойдет, вы не можете быть уверены, просто взглянув на часть кода, и в любом случае проверить намного сложнее.Таким образом, выполнение этого только делает ваш код менее надежным.

Тогда есть возможность предоставить атрибут по умолчанию в качестве атрибута или свойства класса, назначая атрибут объекта только тогда, когда он отличается от значения по умолчанию.Но для вещей, которые, как ожидается, будут варьироваться в зависимости от объекта, ясность наличия каждого атрибута, когда-либо перечисленного в __init__, обычно перевешивает любые потенциальные преимущества задержки доступа к атрибуту экземпляра.

Это не означает, что это неприемлемо, новам нужно будет привести веские аргументы, чтобы это считалось хорошей идеей.

...