2012-04-06 140 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