Can I access class variables using self? - python

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

Yes, you can access the class variable with self. But, in case you have an instance variable, you will be accessing the instance variable when you use self as it is shadowing the class variable.

Related

Python : Using class variables incorrectly?

I have the following classes:
class A(object):
x = 1
class B(A):
pass
class C(A):
pass
When I print the value of x from each class I get:
>>>A.x, B.x, C.x
(1,1,1)
Then I assign 2 to B.x
B.x = 2
A.x, B.x, C.x
>>>(1,2,1)
Everything was normal but when I assigned 3 to A.x I got this :
A.x=3
A.x, B.x, C.x
>>>(3,2,3)
I thought it would return (3,2,1).
This is fundamentally how inheritance works in Python: for class-level variables, it first checks' the classes namespace, then the namespace of every class in the method resolution order. So, both B and C inherit x from A:
In [1]: class A(object):
...: x = 1
...: class B(A):
...: pass
...: class C(A):
...: pass
...:
In [2]: vars(A)
Out[2]:
mappingproxy({'__module__': '__main__',
'x': 1,
'__dict__': <attribute '__dict__' of 'A' objects>,
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'__doc__': None})
In [3]: vars(B)
Out[3]: mappingproxy({'__module__': '__main__', '__doc__': None})
In [4]: vars(C)
Out[4]: mappingproxy({'__module__': '__main__', '__doc__': None})
When you ask for B.x or C.x, it looks into that class namespace, doesn't find any "x", then tries A's namespace, finds it, and returns it.
Now, when you assign a variable to B.x = 2, that adds it to B's class namespace directly:
In [5]: B.x = 2
...:
In [6]: vars(B)
Out[6]: mappingproxy({'__module__': '__main__', '__doc__': None, 'x': 2})
And similarly, when you assign it to A.x=3, it overwrites the old value:
In [7]: A.x=3
...:
In [8]: vars(A)
Out[8]:
mappingproxy({'__module__': '__main__',
'x': 3,
'__dict__': <attribute '__dict__' of 'A' objects>,
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'__doc__': None})
In [9]: vars(B)
Out[9]: mappingproxy({'__module__': '__main__', '__doc__': None, 'x': 2})
In [10]: vars(C)
Out[10]: mappingproxy({'__module__': '__main__', '__doc__': None})
So now, same as before, when you look for C.x, it doesn't find it's own, then it looks for x inside A, and finds it.
Note, inheritance works like this with instances too, just it checks the instance namespace first, then the instances class's namespace, then all the namespace of the classes in it's method resolution order.
I think it's because of this fact that you did not set "a" field for instance of the "C" class.
Thus it gets its default value from the superclass ("Parent class").
If you set the value of "a" in the c instance, You will get "(3,2,1)".

python: print non inherited methods

I am trying to print a list of the methods that have not been inherited from other classes (e.g.., not inheritted from object or another base class). As an example say I have the following class:
class Point:
def __init__(self, x, y):
self.__x=x
self.__y=y
calling this method should print:
[__init__] without __str__ (inheritted from object).
I've tried:
dir(Point)
but the problem is that it includes already inheritted methods.
To print the non-inherited attributes of an object, such as a class object, use vars which checks the __dict__ of that object:
In [1]: class Point:
...: def __init__(self, x, y):
...: self.__x=x
...: self.__y=y
...:
In [2]: vars(Point)
Out[2]:
mappingproxy({'__dict__': <attribute '__dict__' of 'Point' objects>,
'__doc__': None,
'__init__': <function __main__.Point.__init__>,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'Point' objects>})
Since a method is merely a callable object in the class, you can check for it using something to the effect of:
In [3]: for k, v in vars(Point).items():
...: if callable(v):
...: print(k)
...:
__init__
You can look into the __dict__ of the class itself:
import types
def list_methods(t):
for name, item in t.__dict__.items():
if isinstance(item, types.FunctionType):
print(name)
t is a class object here, not an instance of a class. If you want to operate on instances, replace t.__dict__.items() with type(t).__dict__.items() in the loop.

Getting all attributes to appear on python's `__dict__` method

Please consider the following python example:
In [3]: class test(object):
...: attribute='3'
...: def __init__(self):
...: self.other='4'
...:
In [4]: b=test()
In [5]: b.attribute
Out[5]: '3'
In [6]: b.__dict__
Out[6]: {'other': '4'}
Why is it that __dict__ only shows the "other" attribute and not "atribute"?
And how do I get a dictionary with all the classe's attributes and values? That is, how do I get this?
{'other': '4', 'attribute': '3'}
And I mean by using __dict__ or by some other simple means.
PS: related to this question, but couldn't quite get a dict from there.
PS2: I'm not look for test.__dict__ or b.__class__.__dict__, I'm looking for something that can be used as
In [3]: class test(object):
...: attribute='3'
...: def __init__(self):
...: self.other='4'
...: def _print_atr(self):
...: # This should print exactly {'other': '4', 'attribute': '3'}
...: print(self.__all_atr__)
In [4]: b=test()
In [5]: b.attribute
Out[5]: '3'
In [6]: b.__dict__
Out[6]: {'other': '4'}
Cheers
attribute is not an instance attribute but a class attribute (can be seen in the mappingproxy test.__dict__).
You can get attribute in the instance __dict__ if you update the value of attribute from the instance:
>>> b = test()
>>> b.__dict__
{'other': '4'}
>>> b.attribute
'3'
>>> b.attribute = 5
>>> b.__dict__
{'attribute': 5, 'other': '4'}
Or keep the original value with
>>> b.attribute = b.__class__.attribute # may not be necessary
Or you could change the definition of the class and move attribute into one of the class methods and bind it to the instance via self.
b.__dict__ is only a mapping of attributes on b, not on b's class (notice that __init__ isn't there either). The attributes on b's class are on the class's __dict__.
>>> class test(object):
... attribute = 1
... def __init__(self):
... self.other = 2
...
>>> b = test()
>>> b.__dict__
{'other': 2}
>>> test.__dict__
dict_proxy({'__module__': '__main__', 'attribute': 1, '__dict__': <attribute '__dict__' of 'test' objects>, '__weakref__': <attribute '__weakref__' of 'test' objects>, '__doc__': None, '__init__': <function __init__ at 0x1030f72a8>})
If you want both, you can do something like:
d = dict(vars(type(b)))
d.update(vars(b))
(note that some prefer vars(b) to b.__dict__) Of course, this doesn't get subclasses ...
If you want subclasses, you'll need to walk the method resolution order...
d = {}
for cls in type(b).__mro__:
d.update(vars(cls))
d.update(vars(b))
Try typing:
test.__dict__
And it shows a key with 'attribute'. This happens exactly because attribute is a class variable not an instance variable.

Confused about the property decorator and its related getter/setter methods

I've been doing some Python, and I realised I Haven't actually know a lot about the property decorator, so I tried making a simple example. This is the code I used:
class foo():
def __init__(self):
self.__test = 0
#property
def test(self):
return self.__test
#test.setter
def test(self, value):
self.__test = value
#test.getter
def test(self):
self.__test += 1
return self.__test
Then I started playing with it in the interactive shell:
>>> bar = foo()
>>> bar.test
1
>>> bar.test
2
So far the object behaved as I expected it to.
Then I tried checking out the setter method
>>> bar.test = 5
>>> bar.test
5
>>> bar.test
5
Weird. For some reason the value of __test wasn't incremented.
>>> bar._foo__test
2
I thought I had set __test to be equal to 5.
What's going on?
The problem is that your foo class is an old style class, descriptors (and as such properties) are only intended to work with new style classes.
From the doc:
Note that descriptors are only invoked for new style objects or classes (a class is new style if it inherits from object or type)
In this case, with an old style class setting bar.test = 5 creates a test attribute in the instance dict, which shadows the property from the class dict:
>>> bar = foo()
>>> foo.__dict__
{'test': <property object at 0x7f302e64c628>, '__module__': '__main__', '__doc__': None, '__init__': <function __init__ at 0x7f302e658b18>}
>>> bar.test # test property from class dict is used
1
>>> bar.__dict__
{'_foo__test': 1}
>>> bar.test = 5 # sets test on instance
>>> bar.__dict__
{'test': 5, '_foo__test': 1}
So the solution is simple: make foo a new style class by inheriting from object

Python Class. key exists as self.key, but doesn't exists in self.__dict__

My class contain three big dicts, one appear in self.__dict__ other two not.
Example:
class MyClass:
big_matrix = {}
side_array = {}
map_of_data = {}
def __init__( self ):
# etc...
While I'm trying to dump self.__dict__ to terminal, I successfully see only big_matrix and nopt other dicts.
No one array declared in __init__, its declared in other functions, later.
Help me please?
You should initialize your variables in __init__ and assign them to the object self in order to make them belong to the instance namespace (the one that is shown when invoking __dict__ on an object.
Otherwise they are not part of your object instance namespace, but of the class namespace.
Probably you see big_matrix in your instance namespace because you are creating a self.big_matrix somewhere else in the class.
Variables in instance namespace
class MyClass:
def __init__( self ):
self.big_matrix = {}
self.side_array = {}
self.map_of_data = {}
The variables belong to the instance namespace:
>>> print MyClass().__dict__
{'big_matrix': {}, 'side_array': {}, 'map_of_data': {}}
The class doesn't have any variable in its namespace
>>> print MyClass.__dict__
{}
Variables in class namespace
class MyClass:
big_matrix = {}
side_array = {}
map_of_data = {}
The instance doesn't have any variable in its namespace:
>>> print MyClass().__dict__
{}
All the variables belong to the class namespace (plus others used by the class):
>>> print MyClass.__dict__
{'big_matrix': {}, 'side_array': {}, '__module__': '__main__', 'map_of_data': {}, '__doc__': None}
The difference between class attributes and instance attributes is best shown with an example:
In [25]: class MyClass:
....: cls_dict = {} # class attribute
....: def __init__( self ):
....: pass
....:
In [26]:
In [26]: m = MyClass() # first instance
In [27]: m.cls_dict["foo"] = "bar" # first instance adds to dict
In [28]: m1 = MyClass() # second instance
In [29]: m1.cls_dict["bar"] = "foo" # second instance adds to dict
In [30]: MyClass.cls_dict
Out[30]: {'bar': 'foo', 'foo': 'bar'} # both entries in the dict
In [31]: m.cls_dict # can be accessed through the class or an instance
Out[31]: {'bar': 'foo', 'foo': 'bar'}
In [32]: m1.cls_dict
Out[32]: {'bar': 'foo', 'foo': 'bar'}
Instance attribute:
In [33]: class MyClass:
....: def __init__( self ):
....: self.ins_dict = {}
....:
In [34]: m = MyClass()
In [35]: m.ins_dict["foo"] = "bar"
In [36]: m1 = MyClass()
In [37]: m1.ins_dict["bar"] = "foo"
In [38]: m.ins_dict # each instance has its own `ins_dict`
Out[38]: {'foo': 'bar'}
In [39]: m1.ins_dict
Out[39]: {'bar': 'foo'}
class attributes are shared among instances, instance attributes are created for each instance separately.
Any time you change the class attribute cls_dict it will change for both instances.

Categories