Python - 通过模块属性访问类实例(按字符串名称)

时间:2011-01-23 03:27:30

标签: python class attributes module instance

好的,让我尽力解释一下这个问题。假设我有一个名为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个可能性中的一个,我将标记。

所以我想将他们的选择存储在db中(但我只想存储标签,它代表Foobar类的特定实例)。所以我可以抓住我需要的实例。

所以我尝试在这样的模块中设置我的所有实例(让我们称之为“my_instances.py”)

import Foobar

label_one = Foobar("eenie", "meenie", "miney")
label_two = Foobar("teeny", "toony", "tiny")
...
label_ten = Foobar("biggie", "boogie", "baggie")

就这样,一旦我有来自db的代表他们选择的字符串,我就可以像这样抓住那个实例(我忽略了你将如何得到字符串,但显示我是如何获取实例的)。

import my_instances

my_object = getattr(my_instances, 'label_one')
result = my_object.doIt()

我得到一个TypeError:必须使用Foobar实例作为第一个参数调用未绑定方法doIt()。

所以看来我正在接收Foobar,但不是真正的实例。任何帮助将不胜感激。我相信我已经足够解释了我的情况,你会看到我想要做的更简单的解决方法,请提出建议。

3 个答案:

答案 0 :(得分:4)

正如评论所示,您可能在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()

动态符号查找可以很聪明,但不一定更清晰。

答案 1 :(得分:1)

我无法重现您的错误(使用from foobar import Foobar),因此您的代码中似乎没有向我们展示。但最好不要进行动态查找。为什么不创建一个返回foobar字典的工厂函数?

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(...),
           ... } 

答案 2 :(得分:1)

@ payne的查找表创建10个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])