简体   繁体   中英

Setting an attribute on object's __class__ attribute

I am a bit confused over the difference between setting an object's attribute and setting an attribute on an object's __class__ attribute. Roughly, obj.attr vs obj.__class__.attr . What's the difference between them?

Is the former setting an attribute on an instance and the latter setting an attribute on an instance's class (making that attribute available to all instances)? If this is the case, then how are these new class attributes available in Django requests, since the framework works with multiple threads? Does setting a class variable make it persist between requests?

Yes, that is setting the attribute on the class. But no, that would not necessarily make it available between requests, although it might.

Your question shows a misunderstanding of how Django requests work. Django is not necessarily served using multiple threads: in fact, in most server configuration, it is hosted by multiple independent processes that are managed by the server. Again, depending on the configuration, each of those processes may or may not have multiple threads. But whether or not threads are involved, processes are started and killed by the server all the time.

If you set an attribute on a class or module in Django during one request, any subsequent requests served by that same process will see that attribute. But there's no way to guarantee which process your next request will be served by. And there's certainly no way to know if the same user will be accessing the next request from that same process.

Setting things at class or module level can be the source of some very nasty thread-safety bugs. My advice is generally not to do it. If you need to keep things across request, store it in the database, the cache, or (especially if it's specific to a particular user) in the session.

To elaborate on the Python side...

obj.attr is looking for instance attributes and obj.__class__.attr is specifically looking for class attributes.

Note that if you call obj.attr to find an instance attribute, but Python can't find an instance attribute with that name, it then looks in the baseclass for class attributes.

>>> class MyClass():
        foo = "bar"

>>> a = MyClass()
>>> a.foo # class attribute as no instance attribute foo
"bar"
>>> a.foo = "hello" # you are creating a new instance attribute
>>> a.__class__.foo = "goodbye" # you are re-asisgning the value of the class attrribute
>>> a.foo
"hello"
>>> a.__class__.foo
"goodbye"

So now you can have instance attributes and class attributes with the same names.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM