2

因此,我查看了类似的问题,并找到了一些解决方案,但我无法弄清楚如何做到这一点。

我想要做的是从字符串向类添加一个方法。我可以使用该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()

返回这个:

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

如果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

这实质上意味着我不能为类动态创建方法,我知道这是不好的做法并且不符合 Python 标准,因为这些方法将无法访问类的其余部分可以访问的变量。

我很感激任何帮助。

4

2 回答 2

6

You have to bind your function to the class instance to turn it into a method. It can be done by wrapping it in 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()

On a side note, why do you even need exec in this case? You can just as well write

import types

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

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

what().yolo()

Edit: for the sake of completeness, one might prefer a solution through the descriptor protocol:

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

        self.yolo = yolo.__get__(self)

what().yolo()
于 2013-10-06T05:11:17.807 回答
1

另一种方式,对我来说似乎更优雅:

class what:
    pass

ld = {}
exec("""
def yolo(self):
    self.extra = "Hello"
    print(self.extra)
""", None, ld)
# print('locals got: {}'.format(ld))
for name, value in ld.items():
    setattr(what, name, value)

what().yolo()
于 2016-07-20T20:43:03.750 回答