2014-12-05 118 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