简体   繁体   中英

How to dynamically add static methods to a class using exec?

I am trying to dynamically create methods in a class but I'm running into TypeErrors . I suspect that the issue is that I have not bound the method to the class meaning I cannot call it. However, my efforts with types.MethodType have failed. Here's an abstract example:

class cls:

    def __init__(self):
        pass

    def method_adder(self):
        """
        I want to add a method to this class from
        a string
        :return:
        """
        string_func = "@staticmethod\n"
        string_func += "def dynamic_method():"
        string_func += "    return 'I am a dynamically created string to be a new method'"

        exec(string_func, self.__dict__)


c = cls()
print(c)        

Outputs :

<__main__.cls object at 0x7fae0aa08e10>

Then

c.method_adder()
meth = c.dynamic_method
print(meth)     

produces:

<staticmethod object at 0x7f02375ce748>

but actually using the method:

print(meth())   

raises

TypeError: 'staticmethod' object is not callable

Update

I've switched to a 3.7 env as suggested in the comments. I still get the same error but when I remove the @staticmethod decorator the code works as intended. I could probably work with this, but out of curiosity, any idea how to get the code working with a static method?

I was able to get the following to work -- by moving 'setattr' into the exec statement.

class mycls:

    def method_adder(self):
        exec("""
@staticmethod
def f():
    print ('I am a dynamically created string to be a new method')
setattr(mycls, 'df', f)
            """)

c = mycls()
c.method_adder()
mycls.df()

This works:

c = cls()
c.method_adder()
print (c.dynamic_method())

Actually, your original code works for me as well. I'm testing in Python 3.7.3 - what version are you using?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM