Search code examples
pythonpython-3.xinstanceself

Is there self parameter for an object created using type(name, base, dict) method?


Is there a way to simulate the usage of self parameter on an object created using type() method? I want to be able to access the object which was used for calling the method. If I had defined a class then I will be able to access to that object using self parameter. But is it possible to do the same with object created using type()?

In the example below I want to access the instance on which the method getname() was called. (I don't want to pass the object as argument.)

def getname(self):
    return getattr(self, 'name')


obj = type('student', (object,), {"getname":getname})
obj2 = type('student', (object,), {"getname":getname})
setattr(obj, 'name', 'john')
setattr(obj2, 'name', 'peter')
print(obj.getname())
print(obj2.getname())

Solution

  • Your obj and obj2 are the types themselves, not instances of the types. Call the resulting types (to create instances of them) and the methods will be resolved as you expect, passing self (because now you're calling them on instances of the class as bound methods, not referring to the raw function attached to the class itself, which does not bind, and therefore does not implicitly pass self):

    def getname(self):
        return self.name  # No benefit to using getattr(self, 'name'), normal access works identically and is clearer/faster
    
    
    obj = type('student', (object,), {"getname":getname})()  # <- Trailing () creates an instance of the type
    obj2 = type('student', (object,), {"getname":getname})()
    setattr(obj, 'name', 'john')
    setattr(obj2, 'name', 'peter')
    print(obj.getname())
    print(obj2.getname())
    

    Try it online!

    In practice, you probably want to create the type once, then instantiate instances of it from the solo type:

    student = type('student', (object,), {"getname":getname})  # Create the type once
    obj = student()  # Then create two instances
    obj2 = student()
    obj.name = 'john'  # You don't need setattr here, or above
    obj2.name = 'peter'
    print(obj.getname())
    print(obj2.getname())