Is adding attributes not dynamically approved in Python?

In Python, you can assign an arbitrary attribute from outside the defining class :

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

The __dict__ attribute, which supports the dictionary of all attributes, is used as the main mechanism.

We were all told not to expose our internal work to the client code , but attaching new data is not necessarily related to encapsulation, right? Is this idiom common to Python code?


Just what I mean ...

Each Tweet has standard fields, such as id , text , owner .
When you return a list of tweets to a user, you want to display if that tweet is “profitable” by that user.

Obviously, to get is_favorite you need to query the many-to-many relationship for this user .
Would it be ok to preinstall Tweet objects with is_favorite matching the current user ?

Of course, I could set the is_favorite_for(user) method, but I click on the Django template language , which does not allow calling methods with arguments from within the template. In addition, I believe that a template should not call methods at all .


I know this will work fine, but I wonder if something like this in an open source project will force other developers to look at me with contempt.

Sidenote:

I come from C # /. NET, where dynamic types were introduced recently and are not widely adapted, with the exception of some areas of niche (interaction, IoC framework, REST client framework, etc.).

+4
source share
3 answers

I think this is bad practice.

The object does not know that you were busy with your attributes. For example, consider what happens if the Profile is later expanded to have an age attribute that is not associated with p.age in your code.

If you want to add attributes, why not subclass Profile , or have an external Profiles mapping for an object with your custom attributes?

+5
source

I think the answer is: it depends. First, if you really want to prevent it, you can define __slots__ in the class. And it is usually not recommended to add attributes that are not actually defined in the class, as this can confuse someone who reads code and is rarely useful.

But at certain points, it’s useful to be able to do this, and the Python documentation discusses this as a way to get something similar to a C structure or Pascal entry (see http://docs.python.org/tutorial/classes.html in 9.7 "Odds and endings.")

+2
source

If the attribute exists only occasionally, you run the risk of getting an AttributeError from nowhere for one object, while the code worked perfectly for another object of the same class (yes, exact types are not so important when duck-typing, but objects of the same class often considered the same “ducks”). Even if this does not happen, you cannot be sure just by looking at a piece of code, and in any case it will be more difficult to verify. Thus, this makes your code less reliable.

Then it is possible to provide a default attribute as an attribute or property of a class, assigning an attribute of an object only when it differs from the default value. But for things that are expected to change depending on the object, the clarity of each attribute ever specified in __init__ usually exceeds any potential benefits of delaying access to an instance attribute.

This does not mean that it is unacceptable, but you must make a convincing argument for it to be considered a good idea.

+2
source

All Articles