classinstance.__dict__ returns empty dictionary [duplicate] - python

This question already has answers here:
What is the difference between class and instance attributes?
(5 answers)
Closed 6 years ago.
When I define a class with variables already assign, instantiate it and use __dict__ to get variables as a dictionary, I get an empty list.
In [5]:
class A(object):
a = 1
b = 2
text = "hello world"
def __init__(self):
pass
def test(self):
pass
x = A()
x.__dict__
Out[5]:
{}
But when I declare variables in __init__ and use __dict__ it returns variables which were assigned after instantiation of class.
In [9]:
class A(object):
a = 1
def __init__(self):
pass
def test(self):
self.b = 2
self.text = "hello world"
x = A()
x.test()
x.__dict__
Out[9]:
{'b': 2, 'text': 'hello world'}
Why is that __dict__ returning only variables declared after instantiation of class
Edit Answer:
When an instance is created like x = A()
x.__dict__ stores all the instance attributes.
A.__dict__ stores the class attributes

Pls try A.__dict__ to get all class attributes,
x = A()
x.__dict__
here you are calling __dict__ method on A's instance. So the variables associated with that instance should be displayed...
self.b, self.text are instance variables which are specific to particular instance only..

Related

Creating properties dynamically that point to an attribute's properties [duplicate]

This question already has answers here:
What do lambda function closures capture?
(7 answers)
Closed 6 months ago.
I want to make properties from an attribute of my class accessible directly through the instance of the class (without inheriting from it). So basically if I have:
class A:
#property
def foo(self):
print("foo")
#property
def bar(self):
print("bar")
class B:
def __init__(self):
self._a = A()
Instead of doing b._a.bar I want to be able to do b.bar. Based on this answer here, I tried the following in class B:
class B:
def __init__(self):
self._a = A()
attrs = [attr for attr in dir(self._a)
if not callable(self._a.__getattribute__(attr))
and not attr.startswith("__")]
for attr in attrs:
setattr(self.__class__, attr,
property(lambda s: s._a.__getattribute__(attr)))
But when instantiating and testing it out, I get one of those weird python moments:
>>> b = B()
foo
bar
>>> b.foo
bar
>>> b.bar
bar
Why are both 'foo' and 'bar' printed out when creating the instance ?
How does the 'foo' property point to the same getter as 'bar' ?
bar and foo are printed when you create the instance because doing _a.__getattribute__("foo") and _a.foo will both call the property object to get a value.
Both of the attributes you set up in B use lambdas to get the correct property from A. This is a common mistake when calling lambdas. Because the attr value is inherited from the outside scope, it isn't frozen when the lambda is evaluated. Instead, it is simply the same attr reference as the enclosing scope's attr, and changes accordingly. So all of your lambdas will have the same attr value.
You can define a B.__getattr__ method instead. This method is called when ordinary attribute lookup fails.
class B:
def __init__(self):
self._a = A()
def __getattr__(self, name):
return getattr(self._a, name)
b = B()
b.bar # bar
b.foo # foo

Why method can't access class variable?

I am trying to understand variable scopes in Python, most of the things are clear to me except for the part that I don't understand why class variable is not accessible from its method.
In following example mydef1() can't access a, but if a is declared in global scope(outside class definition) it can.
class MyClass1:
a = 25
def mydef1(self):
print(a)
ins1 = MyClass1()
ins1.mydef1()
Output
Traceback (most recent call last):
File "E:\dev\Python\scope_test2.py", line 6, in <module>
ins1.mydef1()
File "E:\dev\Python\scope_test2.py", line 4, in mydef1
print(a)
NameError: name 'a' is not defined
It's important to understand that some of these comments are not equivalent. MyClass.a is a member of the class itself, self.a is a member of the instance of the class.
When you use self.a it will return a from the class, because there is no a on the instance. If there was also an a which was a member of the instance, it would return that instead. Generally the instance a is set using the __init__ constructor. Both of these can exist simultaneously.
class MyClass1:
a = 25
def __init__(self):
self.a = 100
def instance_a(self):
print(self.a)
def change_instance_a(self):
self.a = 5
def class_a(self):
print(MyClass1.a)
def change_class_a(self):
MyClass1.a = 10
# Create two instances
ins1 = MyClass1()
ins2 = MyClass1()
# Both instances have the same Class member a, and the same instance member a
ins1.instance_a()
ins2.instance_a()
ins1.class_a()
ins2.class_a()
# Now lets change instance a on one of our instances
ins1.change_instance_a()
# Print again, see that class a values remain the same, but instance a has
# changed on one instance only
print()
ins1.instance_a()
ins2.instance_a()
ins1.class_a()
ins2.class_a()
# Lets change the class member a on just one instance
ins1.change_class_a()
# Both instances now report that new value for the class member a
print()
ins1.instance_a()
ins2.instance_a()
ins1.class_a()
ins2.class_a()
Short answer: That's Python's scoping rules. Nested functions in Python are lexically scoped, but that doesn't apply to things nested in classes.
class Foo:
a = 25
print(a)
class Bar:
print(a)
The first one prints, but the second is a NameError.
Longer answer:
There is a function closure for class-level variables, but it is all wrapped in __class__. (The main use for this is in the super() magic, which is why it no longer needs arguments in Python 3.)
class MyClass1:
a = 25
def mydef1(self):
print(__class__.a)
ins1 = MyClass1()
ins1.mydef1() # 25
Normally, you'd access such things through the self parameter to allow subclasses to override them, but __class__ would even work for a staticmethod, which has neither self, nor cls.
class MyClass1:
a = 25
#staticmethod
def mydef1():
print(__class__.a)
ins1 = MyClass1()
ins1.mydef1() # 25
The class object technically doesn't even exist until after the class declaration finishes executing, that's why you can't do
class Foo:
a = 25
class Bar:
# NameError: free variable '__class__' referenced before assignment
print(__class__.a)
Nor even,
class Foo:
a = 25
def bar():
print(__class__.a)
# NameError: free variable '__class__' referenced before assignment in enclosing scope
bar()
You can, however, access the locals() dict before then.
class Foo:
a = 21
locals()['a'] *= 2
Foo.a # 42
So this works.
class Foo:
a = 25
global foolocals
foolocals = locals()
def bar():
print(foolocals['a'])
bar() # 25
Consider the following class:
class ScopeTest(object):
classvariable = 0
number_of_objects_created = 0
def __init__(self, value=1):
self.instancevariable = value
ScopeTest.number_of_objects_created += 1
def number_of_brothers(self):
print(ScopeTest.number_of_objects_created)
def confusion(self, value=2):
self.classvariable = value
print (f"class: {ScopeTest.classvariable}, self:{self.classvariable}")
And let's see what happens when you play around with it:
>>> a = ScopeTest()
>>> a.instancevariable
1
>>> a.classvariable
0
>>> ScopeTest.classvariable
0
So far so good, but when you assign a new attribute to a:
>>> a.classvariable = 2
>>> a.classvariable
2
>>> ScopeTest.classvariable
0
The same holds if you add the attribute inside a class's method:
>>> a.confusion(4)
class: 0, self:4
These kind of class attributes are good to keep things common to all objects, as the number_of_objects_created:
>>> b = ScopeTest()
>>> b.number_of_brothers()
2
>>> a.number_of_brothers()
2
You could get a little more from this by adding yet another method to the class:
class ScopeTest(object):
...
def other_function(self, classvariable=3):
print(f"class: {ScopeTest.classvariable}\t"
f"instance: {self.classvariable}\t"
f"argument:{classvariable}")
And calling it (after using the first 'confusion' method to set self.classvariable):
>>> a.confusion()
class: 0, self:2
>>> a.other_function()
class: 0 instance: 2 argument:3
By calling print(a) in mydef1, python is looking for a local (or global, as you discovered) variable "a". That is, a variable not directly related to MyClass1 in any way, but such a variable has not been defined yet.
If you're trying to access the class variable "a" (i.e. a is a member of the class itself, not any instance of it), you must use MyClass1.a. Alternatively, because there is no instance variable named "a", you can also use self.a to the same effect. However, as soon as self.a is explicitly defined, self.a == MyClass1.a may not be true. For example:
>>>class MyClass1:
... a = 25
...
>>>my_obj = MyClass1()
>>>MyClass1.a
25
>>>my_obj.a
25
>>>MyClass1.a += 1
>>>MyClass1.a
26
>>>my_obj.a
26
>>>my_obj.a = 5 # explicitly define "a" for this instance; my_obj.a not longer synonymous with MyClass1.a
>>>MyClass1.a += 1
>>>MyClass1.a
27
>>>my_obj.a
5
You need self.a. There is no implicit class scope.

Can a particular instance of a class make its own variables in python?

Can a particular instance make its own variable in python, if yes would it be available to other instances of the class?
for eg:
class A():
Var1 = 10
inst1 = A()
inst1.Var1 # will be 10
but can inst1 make it's own variables like Var2 etc and will these Variables be available to other class A instances like inst2?
In other Words, is a variable, which is bound to an instance of a class, accessible to another instance of the same class?
Actually, the most common use case is for instances to have their "own" variables ("data attributes" in Python terminology) which are not shared between instances. The variables x and y below are examples of such "own" variables (every instance of class A gets its own variable x when the constructor is called, and inst1 also gets its own variable y later):
class A():
def __init__(self): # Constructor - called when A is instantiated
self.x = 10 # Creates x for self only (i.e. for each instance in turn)
inst1 = A()
inst1.x = 15 # Changes x for inst1 only
inst1.y = 20 # Creates y for inst1 only
print(inst1.x, inst1.y) # 15 20
inst2 = A()
print(inst2.x) # 10
To dynamically add attributes to a class or instance you can use setattr:
class MyClass(object):
pass
my_instance = MyClass()
# add attribute to class
setattr(MyClass, 'new_attribute', 'added')
# Class now has attribute
print(MyClass.new_attribute == 'added') # True
# Which is also available to instance
print(my_instance.new_attribute == 'added') # True
# Add attribute to instance
setattr(my_instance, 'instance_only', 'yup')
# Instance now has attribute
print(my_instance.instance_only == 'yup') # True
# Class does not have attribute
MyClass.instance_only # Raises AttributeError
# Add attribute to instances class
settatr(type(my_instance), 'instance_only', 'not anymore')
# Now the attribute is available to the class as well
print(MyClass.instance_only == 'not anymore') # True
# New instances will also have the attributes
new_instance = MyClass()
print(new_instance.new_attribute == 'added') # True
If you are not adding them dynamically see #gilch's answer
Even though the actual use may be questionable, you actually can bind new attributes to a class definition in a way that they are available to all instances of that class:
class A(object):
attrib_one = 'VALUE'
def add_class_attrib(self, name, value):
# Bind new attribute to class definition, **not** to self
setattr(A, name, value)
if __name__ == '__main__':
# Instantiate _before_ changing A's class attributes
a = A()
b = A()
# Add a new class attribute using only _one_ instance
a.add_class_attrib('attrib_two', 'OTHER')
# Print attributes of both instances
print([e for e in dir(a) if not e.startswith('__')])
print([e for e in dir(b) if not e.startswith('__')])
# Create new instance _after_ changing A's class attribs
c = A()
# Print attributes of new instance
print([e for e in dir(c) if not e.startswith('__')])
Running this code will print the following:
['add_class_attrib', 'attrib_one', 'attrib_two']
['add_class_attrib', 'attrib_one', 'attrib_two']
['add_class_attrib', 'attrib_one', 'attrib_two']
And you see, that -- even if a class attribute is added to the class definition after an instance of it has been created, the newly created class attribute in fact is available to all other instances of that (changed) class.
It depends on if you set the variable in the class's dict or the instance's dict.
>>> class A:
var = 10
>>> inst1 = A()
>>> inst2 = A()
>>> inst1.var # not in instance, so looked up in class
10
>>> inst2.var
10
>>> inst2.var = 20 # instance attr shadows that from class
>>> inst2.var
20
>>> A.var = 30 # class attr can also be altered
>>> inst1.var
30
>>> inst2.var
20
>>> del inst2.var # deleting instance attr reveals shadowed class attr
>>> inst2.var
30
>>> inst1.var2 = 'spam'
>>> inst2.var2 # new attr was set on inst1, so not available in inst2
Traceback (most recent call last):
File "<pyshell#663>", line 1, in <module>
inst2.var2
AttributeError: 'A' object has no attribute 'var2'
>>> inst1.__class__.var3 = 'eggs' # same as A.var3 = 'eggs'
>>> inst2.var3 # new attr was set on the class, so all instances see it.
'eggs'

Where to set the class members in Python? [duplicate]

Is there any difference at all between these classes besides the name?
class WithClass ():
def __init__(self):
self.value = "Bob"
def my_func(self):
print(self.value)
class WithoutClass ():
value = "Bob"
def my_func(self):
print(self.value)
Does it make any difference if I use or don't use the __init__ method for declaring the variable value?
My main worry is that I'll be using it one way, when that'll cause me further problems down the road.
Variable set outside __init__ belong to the class. They're shared by all instances.
Variables created inside __init__ (and all other method functions) and prefaced with self. belong to the object instance.
Without Self
Create some objects:
class foo(object):
x = 'original class'
c1, c2 = foo(), foo()
I can change the c1 instance, and it will not affect the c2 instance:
c1.x = 'changed instance'
c2.x
>>> 'original class'
But if I change the foo class, all instances of that class will be changed as well:
foo.x = 'changed class'
c2.x
>>> 'changed class'
Please note how Python scoping works here:
c1.x
>>> 'changed instance'
With Self
Changing the class does not affect the instances:
class foo(object):
def __init__(self):
self.x = 'original self'
c1 = foo()
foo.x = 'changed class'
c1.x
>>> 'original self'
I would like to add something to the responses that I read in this thread and this thread (which references this one).
Disclaimer: this remarks come from the experiments I ran
Variables outside __init__:
These are, in fact, static class variables and are, therefore, accesible to all instances of the class.
Variables inside __init__:
The value of these instance variables are only accesible to the instance at hand (through the self reference)
My contribution:
One thing that programmers must consider when using static class variables is that they can be shadowed by instance variables (if you are accessing the static class variables through the self reference).
Explanation:
Previously, I thought that both ways of declaring the variables were exactly the same (silly me), and that was partly because I could access both kind of variables through the self reference. It was now, when I ran into trouble, that I researched the topic and cleared it up.
The problem with accessing static class variables through the
self reference is that it only references the static class variable if there is no instance variable with the same name, and to make things worse, trying to redefine a static class variable through the self reference does not work because an instance variable is created which then shadows the previously-accesible static class variable.
To get around this problem, you should always reference static class variables through the name of the class.
Example:
#!/usr/bin/env python
class Foo:
static_var = 'every instance has access'
def __init__(self,name):
self.instance_var = 'I am %s' % name
def printAll(self):
print 'self.instance_var = %s' % self.instance_var
print 'self.static_var = %s' % self.static_var
print 'Foo.static_var = %s' % Foo.static_var
f1 = Foo('f1')
f1.printAll()
f1.static_var = 'Shadowing static_var'
f1.printAll()
f2 = Foo('f2')
f2.printAll()
Foo.static_var = 'modified class'
f1.printAll()
f2.printAll()
Output:
self.instance_var = I am f1
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = every instance has access
self.instance_var = I am f2
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = modified class
self.instance_var = I am f2
self.static_var = modified class
Foo.static_var = modified class
I hope this is helpful to someone
further to S.Lott's reply, class variables get passed to metaclass new method and can be accessed through the dictionary when a metaclass is defined. So, class variables can be accessed even before classes are created and instantiated.
for example:
class meta(type):
def __new__(cls,name,bases,dicto):
# two chars missing in original of next line ...
if dicto['class_var'] == 'A':
print 'There'
class proxyclass(object):
class_var = 'A'
__metaclass__ = meta
...
...
class User(object):
email = 'none'
firstname = 'none'
lastname = 'none'
def __init__(self, email=None, firstname=None, lastname=None):
self.email = email
self.firstname = firstname
self.lastname = lastname
#classmethod
def print_var(cls, obj):
print ("obj.email obj.firstname obj.lastname")
print(obj.email, obj.firstname, obj.lastname)
print("cls.email cls.firstname cls.lastname")
print(cls.email, cls.firstname, cls.lastname)
u1 = User(email='abc#xyz', firstname='first', lastname='last')
User.print_var(u1)
In the above code, the User class has 3 global variables, each with value 'none'. u1 is the object created by instantiating this class. The method print_var prints the value of class variables of class User and object variables of object u1. In the output shown below, each of the class variables User.email, User.firstname and User.lastname has value 'none', while the object variables u1.email, u1.firstname and u1.lastname have values 'abc#xyz', 'first' and 'last'.
obj.email obj.firstname obj.lastname
('abc#xyz', 'first', 'last')
cls.email cls.firstname cls.lastname
('none', 'none', 'none')
In Python, a class comes with member functions (methods), class variables, attributes/instance variables (and probably class methods too):
class Employee:
# Class Variable
company = "mycompany.com"
def __init__(self, first_name, last_name, position):
# Instance Variables
self._first_name = first_name
self._last_name = last_name
self._position = position
# Member function
def get_full_name(self):
return f"{self._first_name} {self._last_name}"
By creating an instance of the object
my_employee = Employee("John", "Wood", "Software Engineer")
we essentially trigger __init__ that is going to initialise the instance variables of the newly created Employee. This means that _first_name, _last_name and _position are explicit parameters of the specific my_employee instance.
Likewise, member functions return information or change the state of a specific instance.
Now any variable defined outside the constructor __init__ are considered to be class variables. Those variables are shared amongst all the instances of the class.
john = Employee("John", "Wood", "Software Engineer")
bob = Employee("Bob", "Smith", "DevOps Engineer0")
print(john.get_full_name())
print(bob.get_full_name())
print(john.company)
print(bob.company)
>>> John Wood
>>> Bob Smith
>>> mycompany.com
>>> mycompany.com
You can also use class methods in order to change the class variable for all the instances of the class. For example:
#classmethod
def change_my_companys_name(cls, name):
cls.company = name
and now change_my_companys_name()
bob.change_my_companys_name("mynewcompany.com")
will have effect on all the instances of class Employee:
print(bob.company)
print(john.company)
>>> mynewcompany.com
>>> mynewcompany.com
Example code:
class inside:
def __init__(self):
self.l = []
def insert(self, element):
self.l.append(element)
class outside:
l = [] # static variable - the same for all instances
def insert(self, element):
self.l.append(element)
def main():
x = inside()
x.insert(8)
print(x.l) # [8]
y = inside()
print(y.l) # []
# ----------------------------
x = outside()
x.insert(8)
print(x.l) # [8]
y = outside()
print(y.l) # [8] # here is the difference
if __name__ == '__main__':
main()
This is very easy to understand if you track class and instance dictionaries.
class C:
one = 42
def __init__(self,val):
self.two=val
ci=C(50)
print(ci.__dict__)
print(C.__dict__)
The result will be like this:
{'two': 50}
{'__module__': '__main__', 'one': 42, '__init__': <function C.__init__ at 0x00000213069BF6A8>, '__dict__': <attribute '__dict__' of 'C' objects>, '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None}
Note I set the full results in here but what is important that the instance ci dict will be just {'two': 50}, and class dictionary will have the 'one': 42 key value pair inside.
This is all you should know about that specific variables.
classes are like blueprints to create objects. Let's make a metaphor with building a house. You have the blueprint of the house so you can build a house. You can build as many houses as your resources allow.
In this metaphor, the blueprint is the class and the house is the instantiation of the class, creating an object.
The houses have common attributes like having a roof, living room, etc. This is where you init method goes. It constructs the object (house) with the attributes you want.
Lets suppose you have:
`class house:`
`roof = True`
`def __init__(self, color):`
`self.wallcolor = color`
>> create little goldlock's house:
>> goldlock = house() #() invoke's class house, not function
>> goldlock.roof
>> True
all house's have roofs, now let's define goldlock's wall color to white:
>> goldlock.wallcolor = 'white'
>>goldlock.wallcolor
>> 'white'
class foo(object):
mStatic = 12
def __init__(self):
self.x = "OBj"
Considering that foo has no access to x at all (FACT)
the conflict now is in accessing mStatic by an instance or directly by the class .
think of it in the terms of Python's memory management :
12 value is on the memory and the name mStatic (which accessible from the class)
points to it .
c1, c2 = foo(), foo()
this line makes two instances , which includes the name mStatic that points to the value 12 (till now) .
foo.mStatic = 99
this makes mStatic name pointing to a new place in the memory which has the value 99 inside it .
and because the (babies) c1 , c2 are still following (daddy) foo , they has the same name (c1.mStatic & c2.mStatic ) pointing to the same new value .
but once each baby decides to walk alone , things differs :
c1.mStatic ="c1 Control"
c2.mStatic ="c2 Control"
from now and later , each one in that family (c1,c2,foo) has its mStatica pointing to different value .
[Please, try use id() function for all of(c1,c2,foo) in different sates that we talked about , i think it will make things better ]
and this is how our real life goes . sons inherit some beliefs from their father and these beliefs still identical to father's ones until sons decide to change it .
HOPE IT WILL HELP
As noted by S.Lott,
Variable set outside init belong to the class. They're shared by
all instances.
Variables created inside init (and all other method functions) and
prefaced with self. belong to the object instance.
However,
Note that class variables can be accessed via self.<var> until they are masked by an object variable with a similar name This means that reading self.<var> before assigning it a value will return the value of Class.<var> but afterwards it will return obj.<var> . Here is an example
In [20]: class MyClass:
...: elem = 123
...:
...: def update(self,i):
...: self.elem=i
...: def print(self):
...: print (MyClass.elem, self.elem)
...:
...: c1 = MyClass()
...: c2 = MyClass()
...: c1.print()
...: c2.print()
123 123
123 123
In [21]: c1.update(1)
...: c2.update(42)
...: c1.print()
...: c2.print()
123 1
123 42
In [22]: MyClass.elem=22
...: c1.print()
...: c2.print()
22 1
22 42
Second note: Consider slots. They may offer a better way to implement object variables.
Try this and check the difference
class test:
f = 3
def __init__(s, f):
s.__class__.f = f
s.f = s.__class__.f
print(f'def __init__(s, {f})')
print(f's.__class__.f = {f}')
print(f's.f={s.__class__.f}')
print(f'f={f}')
print('===============init over===========')
def setinstancetoOne(s, f):
print(f'def setinstancetoOne(s, {f})')
s.f = f
print(f'class var f = {f}')
def useClassname(test):
print(f'>>>>def useClassname({test})')
print(f'test.f {test.f}')
def p_method(s):
print(f'>>>>def p_method({s})')
print(f's.f {s.f}')
print(f'test.f {test.f}')
print(f's.__class__.f {s.__class__.f}')
print(f'class var f={f}')
# test.__init__.f = 19
t = test(2)
t.useClassname()
t.p_method()
print(f'Outside class t.f {t.f}')
print(f'Outside class test.f {test.f}')
print('______difference__________')
t = test(2)
t.setinstancetoOne(1)
t.useClass()
t.p_method()
print(f'Outside class instance variable(2) {t.f}')
print(f'Outside class class variable(3) {test.f}')

Meaning of self.__dict__ = self in a class definition

I'm trying to understand the following snippet of code:
class Config(dict):
def __init__(self):
self.__dict__ = self
What is the purpose of the line self.__dict__ = self? I suppose it overrides the default __dict__ function with something that simply returns the object itself, but since Config inherits from dict I haven't been able to find any difference with the default behavior.
Assigning the dictionary self to __dict__ allows attribute access and item access:
>>> c = Config()
>>> c.abc = 4
>>> c['abc']
4
As per Python Document, object.__dict__ is:
A dictionary or other mapping object used to store an object’s (writable) attributes.
Below is the sample example:
>>> class TestClass(object):
... def __init__(self):
... self.a = 5
... self.b = 'xyz'
...
>>> test = TestClass()
>>> test.__dict__
{'a': 5, 'b': 'xyz'}

Categories