2012-04-06 122 views
2

我對URL和它們的頭一個容器類,資源:從Python字典鍵創建變量

class Resource(object): 
    def __init__(self, url, headers): 
     self.url = url 
     self.content-length = headers['content-length'] 
     self.content-type = headers['content-type'] 

     # etc.... 

headers參數來__init__方法需要從urllib2.urlopen()getinfo()方法返回一個字典。我認爲這將是打包資源網址和標題的更可讀方式。一遍又一遍地輸入self.someheader = headers['someheader']讓我想知道是否有某種方法可以像這樣的字典鍵自動創建變量。這可能嗎?

+4

這不是有效的Python!如果你意識到這一點,你也會意識到爲什麼不可能爲通用的詞典做到這一點。 – 2012-04-06 11:08:02

+0

這有點危險。就像PHP自動變量一樣。 – 2012-04-06 11:08:27

+1

@PabloSantaCruz是什麼讓它變得危險?它是否會造成某種安全問題? – muskrat 2012-04-06 11:16:52

回答

4

Python標識符中不能有-符號!所以我們可以用鑰匙中的_代替它。
將鍵改爲小寫使它們看起來像一個傳統的變量名,而且,非常重要的是,刪除大寫/小寫混淆(因爲標題通常使用大寫鍵發送)。

for k, v in headers.items(): 
    setattr(self, k.lower().replace('-', '_'), v) 

如果你使用的是Python 2,iteritems是更好地在這裏,因爲它不創建項目的一個新的列表,但只是讓你在它們之間迭代,它是由Python 3的默認操作。

將這些密鑰存儲在「私人」字典(例如self._headers)中可能是一個好主意。然後,您可以通過__getattr____setattr__更好地控制此過程,例如,在嘗試設置無效密鑰時可能會引發異常。

+0

當然這適用於'header_name =='content-length'' ?? – 2012-04-06 11:09:15

+0

@NiklasB .:是的。那麼,你現在可以刪除評論...我在你的評論之前編輯了答案。 – 2012-04-06 11:12:45

+0

感謝提交給'__getattr__'和'__setattr__'的堆,這是一個更好的方式來做我想做的事情 – muskrat 2012-04-06 12:23:23

1

考慮使用一個類,如下面的

class ADict(dict): 
    def __getattr__(self, field): 
     return self.get(field) 

那麼這將讓你簡單地包裹你的頭在裏面。正如其他人所指出的那樣 - 仍然不允許你訪問包含短劃線的屬性,但是你可以使用getattr來訪問這些屬性。請看下面的頭,裹着ADict

header = {'content-type': 'text/javascript', 'content-length': 30, 'accept': 'text/html'} 
aheader = ADict(header) 

屬性如接受可以使用熟悉的點語法,而無效的屬性來訪問可以被訪問通過getattr

>>>> aheader.accept 
'text/html' 
>>>> getattr(aheader, 'content-length') 
30