I have a class Foo with a class variable remote. Can I access the class variable remote using self.remote?
class Foo:
remote = False
def __init__(self):
self.remote = True
@classmethod
def print_remote(cls):
print(cls.remote) #prints False but why?
Assigning remote to self in __init__ means that instance.remote is found first when you access it through self (granted no descriptors are around). To get both options, access either from self or from type(self), that is, either from the instance or the class:
def print_remote(self):
print(type(self).remote) # class remote
print(self.remote) # instance remote
type(self).remote is essentially equivalent to self.__class__.remote but, in general, you should avoid grabbing dunder names (__*__) when there's a built in that does it for you (type in this case)
These live in different dictionaries and are different variables. self.remote lives in the instance dict while class.remote in the class dict.
>>> Foo().__dict__['remote']
True
>>> Foo.__dict__['remote']
False
When you access through cls with a classmethod (or type(self) in a normal method) you'll get the class one, when you access through self you get the instance one.
In [1]: class Foo:
...: x = 0
...:
In [2]: f = Foo()
In [4]: f.__dict__ # empty
Out[4]: {}
In [5]: Foo.__dict__ # have the variable x = 0
Out[5]:
mappingproxy({'__dict__': <attribute '__dict__' of 'Foo' objects>,
'__doc__': None,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'Foo' objects>,
'x': 0})
When you try access a variable in a object, Python will look first in the object, if it is not there then it looks in class dict.
In [6]: Foo.x = 10 # changing class variable
In [7]: f.__dict__ # still empty.
Out[7]: {}
In [8]: f.x # gives you Foo's x as object doesn't have that item.
Out[8]: 10
In [9]: f.x = 20 # this line creates a new variable in x. Now both class and object has their own variable x
In [10]: f.__dict__ # f has its own x.
Out[10]: {'x': 20}
In [11]: Foo.__dict__ # Foo has its own x.
Out[11]:
mappingproxy({'__dict__': <attribute '__dict__' of 'Foo' objects>,
...
'x': 10})
In [12]: f.x # always you will get the value from f.__dict__
Out[12]: 20
In [16]: f.x = 50 # changing the value of object's variable
In [17]: Foo.x # above statement didn't affect class's variable.
Out[17]: 10
In [13]: del f.x # delete object's x
In [14]: f.x # now f doesn't have x, you get the value from class Foo.
Out[14]: 10
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With