我想从用户输入的字符串创建类的实例,所以我使用了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
答案 0 :(得分: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}