【发布时间】:2016-02-09 22:56:36
【问题描述】:
我需要使用 setattr 从配置文件中读取,并将类的属性设置为另一个模块中的函数。粗略来说,这就是问题所在。
这行得通:
class MyClass:
def __init__(self):
self.number_cruncher = anothermodule.some_function
# method works like this, of course;
foo = MyClass()
foo.number_cruncher(inputs)
好的,这很简单,但是如果我想从配置文件中读取some_function 的名称怎么办?读取文件并使用 setattr 也很简单:
def read_ini(target):
# file reading/parsing stuff here, so we effectively do:
setattr(target, 'number_cruncher', 'anothermodule.some_function')
bar = MyClass()
read_ini(bar)
bar.number_cruncher(inputs)
这给了我一个 'str' object is not callable 错误。如果我理解正确,那是因为在第一种情况下,我将属性设置为对另一个模块的引用,但在第二种情况下,它只是将属性设置为字符串。
问题:1) 我对这个错误的理解正确吗? 2) 如何使用setattr 将属性设置为对函数的引用而不是简单的字符串属性?
我查看了其他问题并发现了类似的问题,但似乎没有任何问题可以准确解决这个问题。
【问题讨论】:
-
模块是提前知道的,还是需要根据字符串加载模块?
-
你是说
anothermodule.some_function的值是从文件中读取的吗?如果是这样,您希望使用动态导入,并在生成的模块对象上使用getattr()将该字符串解析为函数对象。 -
否则,如果
anothermodule.some_function是静态的(在您编写代码时已知),那么只需使用etattr(target, 'number_cruncher', anothermodule.some_function)。第三个参数不必是字符串,它是您要用作所设置属性值的实际对象。 -
编辑:@MartijnPieters 基本上已经说过了...
setattr的第三个参数是您设置的值,所以如果这是一个字符串,您就设置一个字符串。如果它是一个 int,它将是一个 int 等,然后是一个对象的对象。 -
模块已知并已导入。基本上,它是一个可能的函数库。查看下面的答案,但我认为他们已经解决了。