Meaning of self.__dict__ = self in a class definition - python

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'}

Related

Why is an object not created when a method is called during the object's contruction?

Given the class test, why it is not possible to instantiate it by calling one of its methods along with the constructor?
class test:
def __init__(self, a):
self.a = a
def print_a(self):
print(self.a)
Here is an example:
>>> obj = test("Hello").print_a() # Prints the desired output.
Hello
>>> obj
>>> print(obj) # But the object does not exist.
None
>>> obj = test("Hello") # It obviously works when doing it separately.
>>> obj
<__main__.test object at 0x7f537fea3940>
>>> obj.print_a()
Hello
Why is it not possible to chain a method call with the constructor call?
This was implemented in python3.
You are assigning obj to the return value of the function print_a (which is None as it has no return). The actual test object was never stored and is therefore no longer in scope when you try to print it.

Call constructor of cls object in Python

I am trying to call the constructor of a class object in python. I managed to get it to work using the following few lines:
obj = cls.__new__(cls)
n = (List of attribute names)
v = (List of attribute values)
for s in n:
setattr(obj, s, v[s])
I was wondering if there is a way to directly insert the attribute value + name pairs into the constructor, cause the arguments are just ignored if i call the following:
obj = cls.__new__(cls, v)
p.s.: I am using python3
The class looks similar to this:
class InheritingClass(BaseClass):
def __init__(self, basic_attribute, another_attribute=None):
super().__init__(basic_attribute=basic_attribute)
self.another_attribute= another_attribute
class BaseClass:
def __init__(self, basic_attribute=1):
self.basic_attribute= basic_attribute
So nothing special there
I was wondering if there is a way to directly insert the attribute value + name pairs into the constructor
Please don't do that. This would be the anti pattern. Instead, use the __init__ method to set the values. The __new__ method should be the memory space allocation that returns the object instance, obj in your case.
So you should probable better do this inside your __init__:
k = ['a', 'b', 'c']
v = [1, 2, 3]
d = dict(zip(k, v))
class C:
def __init__(self, d):
for _ in d:
setattr(self, _, d[_])
ci=C(d)
print(ci.a) # 1
I used the dict as __init__ parameter, where I used the zip method to create one.
__init__ is the constructor of Python class instead of __new__. Refer Pythons use of new and init for more information.
To add, if you want to store arbitrary attributes to your class, you can use dict.update like so:
class BaseClass:
def __init__(self, basic_attribute=1, **kw):
self.basic_attribute = basic_attribute
self.__dict__.update(**kw)
class InheritingClass(BaseClass):
def __init__(self, basic_attribute, another_attribute=None, **kw):
super().__init__(basic_attribute=basic_attribute, **kw)
self.another_attribute = another_attribute
Then:
ic = InheritingClass('hi', a=1, b=20)
print(ic.a, ic.b) # prints 1, 20
To answer the question "How do you call the constructor on a class object?" you need to look at the comments from Amadan way back on Aug 24, 2016 at 6:41.
The answer:
new_obj = cls()
Here's some example code that illustrates the point:
class C:
#classmethod
def c(cls):
return cls()
c = C.c()
print(c) # displays <__main__.C object at 0x10ef16a90>
class D(C):
pass
d = D.c()
print(d) # displays <__main__.D object at 0x10ef16370>
And so we see that you can instantiate an object from the cls object.
Now if we combine Amadan's comment with prosti's cool code for setting attributes, we get this:
class ObjectFactory:
#classmethod
def new(cls,**kwargs):
return cls(**kwargs)
def __init__( self, **kwargs ):
for _ in kwargs:
setattr( self, _ , kwargs[ _ ] )
class Person(ObjectFactory):
pass
person = Person.new( first = "John", last = "Doe" )
print(person) # <__main__.Person object at 0x10fe49ff0>
print(person.__dict__) # {'first': 'John', 'last': 'Doe'}

classinstance.__dict__ returns empty dictionary [duplicate]

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..

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 members with dynamic names

I've seen a class in python which does something of this kind:
obj = Class( name = "somename" )
obj.somename = something
Namely the class initialisation created a member called as the argument string.
I cannot manage to reproduce this behaviour. Any ideas?
I managed to do something similar using globals()["name"] = value. But in this case the created object is son of the module not of the "Class" object. And it's callable as module.somename instead of obj.somename.
You can easily create a dynamically named member by using setattr:
>>> class Foo(object):
... def __init__(self, name):
... setattr(self, name, 42)
...
>>> f = Foo('bar')
>>> f.bar
42
>>> f.bar = 'hello'
>>> f.bar
'hello'
Note however, that just setting any attribute on an instance of a class is possible for any regular class (that doesn't define __slots__):
>>> class Qux(object):
... pass
...
>>> q = Qux()
>>> q.foobar = 'hello'
>>> q.foobar
'hello'
You can either create a dynamically named fixed value property like this:
class MyClass():
def __init__(self, attr):
self.__dict__[attr] = 'some_value'
Or create as many properties as the calling function wants:
class MyClass():
def __init__(self, *argv, **kwargs):
for key,value in kwargs.items():
self.__dict__[key] = value

Categories