exec将一个函数添加到一个类中

Hov*_*tar 2 python exec setattr

所以我看了类似的问题,我找到了一些解决方案,但我不知道如何做到这一点.

我想要做的是从字符串向类中添加一个方法.我可以使用该setattr()方法执行此操作,但这不会让我self在额外方法中用作属性.这是一个例子:(我为变量名称道歉,当我嘲笑一个想法时,我总是使用yolo)

class what:
    def __init__(self):
        s = 'def yolo(self):\n\tself.extra = "Hello"\n\tprint self.extra'
        exec(s)
        setattr(self,"yolo",yolo)

what().yolo()
Run Code Online (Sandbox Code Playgroud)

返回:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: yolo() takes exactly 1 argument (0 given)
Run Code Online (Sandbox Code Playgroud)

如果s = 'def yolo():\n\tself.extra = "Hello"\n\tprint self.extra' 那时我得到这个结果:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 2, in yolo
NameError: global name 'self' is not defined
Run Code Online (Sandbox Code Playgroud)

这实际上意味着我不能动态地为类创建方法,我知道这是不好的做法和unpythonic,因为这些方法无法访问类的其余部分可以访问的变量.

我感谢任何帮助.

fja*_*rri 6

您必须将函数绑定到类实例以将其转换为方法.它可以通过将其包装在types.MethodType:

import types

class what:
    def __init__(self):
        s = 'def yolo(self):\n\tself.extra = "Hello"\n\tprint self.extra'
        exec(s)
        self.yolo = types.MethodType(yolo, self)

what().yolo()
Run Code Online (Sandbox Code Playgroud)

另外,exec在这种情况下你为什么还需要?你也可以写

import types

class what:
    def __init__(self):
        def yolo(self):
            self.extra = "Hello"
            print self.extra

        self.yolo = types.MethodType(yolo, self)

what().yolo()
Run Code Online (Sandbox Code Playgroud)

编辑:为了完整起见,人们可能更喜欢通过描述符协议的解决方案:

class what:
    def __init__(self):
        def yolo(self):
            self.extra = "Hello"
            print self.extra

        self.yolo = yolo.__get__(self)

what().yolo()
Run Code Online (Sandbox Code Playgroud)