Call constructor of cls object in Python

Question:

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

Asked By: Rittel

||

Answers:

__init__ is the constructor of Python class instead of __new__. Refer Pythons use of new and init for more information.

Answered By: Moinuddin Quadri

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
Answered By: bananafish

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.

Answered By: prosti

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'}
Answered By: Mark
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.