开发者

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:

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. 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.

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). 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")

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')
resu开发者_运维技巧lt = my_object.doIt()

I am getting a TypeError: unbound method doIt() must be called with Foobar instance as first argument.

So it appears I'm getting Foobar, but not a real instance of it. 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.

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.


@payne's lookup table creates ten instances of Foobar and then returns the one you want to use; 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])


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. But it's better not to do dynamic lookup anyway. Why not create a factory function that returns a dict of foobars?

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,

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

def get_foobars():
    return foobars

Or, more tersely,

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜