所以我看了类似的问题,我找到了一些解决方案,但我不知道如何做到这一点。
我要做的是从字符串向类添加方法。我可以使用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
这实际上意味着我不能动态地为类创建方法,我知道这是不好的做法和unpythonic,因为这些方法无法访问类的其余部分可以访问的变量。
我感谢任何帮助。
答案 0 :(得分:5)
您必须将函数绑定到类实例以将其转换为方法。可以通过将其包装在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()
另一方面,为什么在这种情况下你甚至需要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()
编辑为了完整起见,人们可能更喜欢the descriptor protocol的解决方案:
class what:
def __init__(self):
def yolo(self):
self.extra = "Hello"
print self.extra
self.yolo = yolo.__get__(self)
what().yolo()
答案 1 :(得分: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()