简体   繁体   English

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

[英]Python - Getting access to class instance via module property (by string name)

Ok, let me try and explain this to the best of my ability. 好吧,让我尝试尽我所能解释一下。 Lets say I have a class called Foobar: 可以说我有一个叫做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

and I want to have a set of 10 possibilities of instances of Foobar that I will use in my application. 我想在应用程序中使用一组10种Foobar实例的可能性。 Now my end user does not know or care about the values of foo, bar and choo, but would would like to pick one of the 10 possibilities, which I will label. 现在,我的最终用户不了解或不关心foo,bar和choo的值,但想选择10种可能性之一,我将它们标记为。

So I would like to store their choice in a db (but I only want to store the label, which represents a particular instance of the Foobar class). 因此,我想将他们的选择存储在数据库中(但我只想存储标签,该标签代表Foobar类的特定实例)。 So that way i can just grab the instance I need. 这样,我就可以获取所需的实例。

So I tried setting up all my instances in a module like so (lets call it "my_instances.py") 因此,我尝试像这样在模块中设置所有实例(让我们将其称为“ my_instances.py”)

import Foobar

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

and that way, once I have the string from the db that represents their choice, I can grab that instance like so (I'm ignoring how you would get the string, but showing how I'm obtaining the instance). 这样,一旦我从数据库中获得代表他们选择的字符串,就可以像这样抓取该实例(我忽略了如何获取字符串,但显示了如何获取实例)。

import my_instances

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

I am getting a TypeError: unbound method doIt() must be called with Foobar instance as first argument. 我收到一个TypeError:必须以Foobar实例作为第一个参数来调用未绑定方法doIt()。

So it appears I'm getting Foobar, but not a real instance of it. 看来我正在使用Foobar,但不是它的真实实例。 Any help would be greatly appreciated. 任何帮助将不胜感激。 I believe I've explained my scenario enough that is you see a simpler workaround for what I am trying to do, please suggest it. 我相信我已经对我的情况进行了足够的解释,以便您看到我要尝试的操作更简单的解决方法,请提出建议。

As the comment suggests, you likely have a name collision between Foobar the class and Foobar the module. 由于意见建议,你可能有之间的名称冲突Foobar类和Foobar模块。

However, it might be clearer to explicitly define a lookup table: 但是,显式定义查找表可能会更清楚:

foobars = {
  'label_one': Foobar("eenie", "meenie", "miney"),
  'label_two': Foobar("teeny", "toony", "tiny"),
  ...
  'label_ten': Foobar("biggie", "boogie", "baggie")
}

Usage: 用法:

result = foobars['label_one'].do_it()

Dynamic symbol lookups can be clever, but aren't necessarily clearer. 动态符号查找可能很聪明,但不一定更清晰。

I can't reproduce your error, (using from foobar import Foobar ) so it seems there's something in your code that you're not showing us. 我无法重现您的错误(( from foobar import Foobar ),因此似乎您的代码中有某些内容没有显示给我们。 But it's better not to do dynamic lookup anyway. 但是最好还是不要进行动态查找。 Why not create a factory function that returns a dict of foobars? 为什么不创建一个返回foobar字典的工厂函数?

def get_foobars(x, y, z):
    foobars = {}
    foobars["label_one"] = Foobar(x, y, z)
    foobars["label_two"] = Foobar(z, y, x)
    ...

Or, if you don't want the function to create new foobars every time, 或者,如果您不希望函数每次都创建新的foobar,

foobars = {}
foobars["label_one"] = Foobar(...

def get_foobars():
    return foobars

Or, more tersely, 或者,更简洁地说

foobars = {'label_one':Foobar("eenie", "meenie", "miney"), 
           'label_two':Foobar(...),
           ... } 

@payne's lookup table creates ten instances of Foobar and then returns the one you want to use; @payne的查找表创建了十个Foobar实例,然后返回您要使用的那个实例; this seems wasteful. 这似乎很浪费。 Why not instantiate on demand, like so? 为什么不按需实例化呢?

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])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM