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