Question

I have a generic class that I add dynamic properties to, and I want to add methods dynamically to instances, as certain instances will have different methods, but they need to access these dynamic properties.

How do I do this?

class GenericComponent:
    def __init__(self, ID):
        self.ID = ID

    @classmethod
    def addMethod(cls, func):
        return setattr(cls, func.__name__, types.MethodType(func, cls))

In my logic, as I build up these generic components I have something like this, so that for different instances I will have the same method name, but the logic inside it is different.

            if t==0:
                def toString(target):
                   print "toString: ", target
                   attrs = vars(target)
                   print ', '.join("%s: %s" % item for item in attrs.items())              
                obj = GenericComponent(ID)
                obj.ID = ID
                obj.name = "some random name"
                obj.addMethod(toString)
                obj.toString()

Unfortunately when I call obj.toString() it won't see obj.name

Was it helpful?

Solution

You've made addMethod a class method. Python class methods can be called on an instance, as you do here with obj.addMethod(toString), but in that case the instance is used only to get its class; the first argument passed to addMethod is the class of obj.

Your addMethod call then makes the function passed as its second argument (in this example, toString) a bound method of the class. The instruction obj.toString() then first searches for the toString attribute of obj; that lookup process finds an attribute of the class that's also callable. But what you invoke then is not a bound method of the instance, but a bound method of the class. The method is then called with the class as the value of target and so it prints the attributes of the class, not those of the instance.

I'm not sure what exactly you're trying to achieve, but perhaps this is closer to what you want:

class GenericComponent:
    def __init__(self, ID):
        self.ID = ID
    def addMethod(self, func):
        return setattr(self, func.__name__, types.MethodType(func, self))

def toString(target):
    print "toString: ", target
    attrs = vars(target)
    print ', '.join("%s: %s" % item for item in attrs.items())
ID = 'some ID'
obj = GenericComponent(ID)
obj.name = "some random name"
obj.addMethod(toString)
obj.toString()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top