2014-12-05 88 views
1

我想创建一个类的实例从一个字符串用户输入,所以我用exec()函数。问题是我无法通过函数外部的名称来访问实例。我的第一个想法是,它是一个函数范围的问题,我仍然认为它是,但是当我将实例放入列表中时,我可以访问它们,而不是使用它们的名称。我真的不知道这里发生了什么..有没有办法让我可以通过他们的名字来访问实例,比如thing1.properties,但是在函数之外,因为这不是我的整个代码,所以将所有的函数放在外面会很麻烦?就像在函数中创建实例列表并“提取”函数外的所有实例一样,以便我可以在函数之外访问它们。下面是代码:类和函数范围

class Things: 
    def __init__(self, properties): 
     self.properties = properties 

listt = [] 
def create_instance(): 
    exec("thing1=Things('good')") 
    listt.append(thing1) 

create_instance() 
print listt[0].properties 
print thing1.properties 
+4

这是几乎可以肯定实现你的目标的一个非常贫困的方法。你想做什么? – rlms 2014-12-05 18:44:11

+0

我在问题中写道。我想从输入的字符串用户创建一个类的实例。因此,当用户键入“thing1”实例thing1 = Things()时创建。如果有更好的方法来做到这一点,我想你会与我分享。 – 2014-12-05 18:47:35

+3

污染全局范围在Python中被忽视。您可能应该将实例存储在字典中。 – 2014-12-05 18:50:26

回答

1

虽然我痛恨污染全局命名空间,exec语句可以采取第二个参数作为范围,并默认为locals()

>>> def foo(name): 
...  exec "{} = 1".format(name) 
... 
>>> def bar(name): 
...  exec "{} = 1".format(name) in globals() 
... 
>>> foo('a') 
>>> a 
Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
NameError: name 'a' is not defined 
>>> bar('a') 
>>> a 
1 

所以,如果你传递globals作为范围,它会按你的想法工作,但真的吗?污染全球范围本身是可怕的,在评估用户提供的代码时这样做是一个可怕的责任。

[更新]

非常有帮助!谢谢!但现在更好的方法是做什么,字典或全球范围?

也许可以将所有实例存储到一个类变量,例如:

class Thing(object): 
    instances = {} 
    def __init__(self, name, **properties): 
     self.name = name 
     self.properties = properties 
     self.instances[name] = self 
    def __repr__(self): 
     t = '<"{self.name}" thing, {self.properties}>' 
     return t.format(self=self) 

现在你可以这样做:

# declare your things 
>>> Thing('foo', a=1, b=2) 
>>> Thing('bar', a=3, b=4) 

# retrieve them by name 
>>> Thing.instances.get('foo') 
<"foo" thing, {'a': 1, 'b': 2}> 

>>> Thing.instances.get('foo').properties 
{'a': 1, 'b': 2} 

>>> Thing.instances.get('bar').properties 
{'a': 3, 'b': 4} 
+0

非常有帮助!谢谢!但现在更好的方法是做什么,字典或全球范围? – 2014-12-05 19:12:13

+0

@NikolaLošić用建议的方法查看我的更新 – 2014-12-05 19:31:48