Python - 通过字符串名称访问模块属性中的类实例
好的,让我尽量用简单的方式来解释这个问题。假设我有一个叫做 Foobar 的类:
class Foobar():
def __init__(self, foo, bar, choo):
self.foo = foo
self.bar = bar
self.choo = choo
def doIt(self):
return self.foo + self.bar
我想在我的应用程序中使用 10 种 Foobar 的实例。我的最终用户并不知道 foo、bar 和 choo 的具体值,也不在乎这些,但他们想从这 10 种可能性中选择一种,我会给这些选择贴上标签。
所以我想把他们的选择存储在数据库里(但我只想存储标签,这个标签代表了 Foobar 类的某个特定实例)。这样我就可以直接获取我需要的实例。
我尝试在一个模块中设置所有的实例,像这样(我们叫这个模块 "my_instances.py"):
import Foobar
label_one = Foobar("eenie", "meenie", "miney")
label_two = Foobar("teeny", "toony", "tiny")
...
label_ten = Foobar("biggie", "boogie", "baggie")
这样一来,当我从数据库中获取到代表他们选择的字符串时,我就可以像这样获取那个实例(我不讨论如何获取这个字符串,只是展示我是如何获取实例的)。
import my_instances
my_object = getattr(my_instances, 'label_one')
result = my_object.doIt()
但是我遇到了一个错误:TypeError: unbound method doIt() must be called with Foobar instance as first argument。
看起来我得到了 Foobar,但并不是它的真实实例。任何帮助都会非常感谢。我相信我已经把我的情况解释得够清楚了,如果你看到更简单的解决办法,请告诉我。
3 个回答
我无法重现你遇到的错误(使用 from foobar import Foobar
),所以看起来你的代码中有一些我们没有看到的部分。不过,动态查找其实不是个好主意。为什么不创建一个工厂函数,返回一个包含多个foobars的字典呢?
def get_foobars(x, y, z):
foobars = {}
foobars["label_one"] = Foobar(x, y, z)
foobars["label_two"] = Foobar(z, y, x)
...
或者,如果你不想每次都让这个函数创建新的foobars,
foobars = {}
foobars["label_one"] = Foobar(...
def get_foobars():
return foobars
或者,更简洁一点,
foobars = {'label_one':Foobar("eenie", "meenie", "miney"),
'label_two':Foobar(...),
... }
正如评论所说,你可能在类 Foobar
和模块 Foobar
之间发生了名字冲突。
不过,明确地定义一个查找表可能会更清晰:
foobars = {
'label_one': Foobar("eenie", "meenie", "miney"),
'label_two': Foobar("teeny", "toony", "tiny"),
...
'label_ten': Foobar("biggie", "boogie", "baggie")
}
用法:
result = foobars['label_one'].do_it()
动态符号查找可能很聪明,但不一定更清晰。
@payne 的查找表创建了十个 Foobar 的实例,然后再返回你想用的那个;这看起来有点浪费。为什么不按需创建实例呢,像这样?
class Foobar():
def __init__(self, foo, bar, choo):
self.foo = foo
self.bar = bar
self.choo = choo
def doIt(self):
return self.foo + self.bar
makeFooLookup = {
"first": ("eenie", "meenie", "miney"),
"second": ("teeny", "toonie", "tiny"),
"third": ("biggie", "baggie", "boogie")
}
def makeFoo(label, lookup=makeFooLookup):
return Foobar(*lookup[label])