经过一段时间的Javascript编程后,我对对象和关联数组(字典)之间的二元性有了一点关注:
//Javascript
var stuff = { a: 17, b: 42 };
stuff.a; //direct access (good sugar for basic use)
stuff['a']; //key based access (good for flexibility and for foreach loops)
在python中,基本上有两种方法可以做这种事情(据我所知)
字典:
stuff = { 'a': 17, 'b':42 };
# no direct access :(
stuff['a'] #key based access
或对象:
#use a dummy class since instantiating object does not let me set things
class O(object):
pass
stuff = O()
stuff.a = 17
stuff.a = 42
stuff.a #direct access :)
getattr(stuff, 'a') #key based access
编辑:有些回复还提到了 namedtuples 作为为不可变对象创建轻量级类的buitin方法。
所以我的问题是:
是否有关于我是否应该使用dicts或对象存储简单的无方法键值对的最佳实践?
我可以想象有很多方法可以创建小辅助类来使对象方法不那么难看(例如,在构造函数上接收dict然后覆盖__getattribute__
)。这是一个好主意还是我过度思考?
答案 0 :(得分:8)
不确定"已建立的最佳做法",但我所做的是:
**kwargs
是一个词典,所以我选择了dicts。或者换句话说,用对象表示数据类型的实例。用dicts表示临时或临时映射。 Swallow不得不使用['key']
语法 - 让Python感觉像Javascript一样让我感到被迫。
答案 1 :(得分:4)
好吧,如果密钥是提前知道的(实际上,甚至不是真的),你可以使用命名元组,这些元组基本上都是用你选择的字段轻松创建的对象。主要的限制是你必须在创建元组类时知道所有键,它们是不可变的(但你可以获得更新的副本)。
http://docs.python.org/library/collections.html#collections.namedtuple
此外,您几乎可以肯定创建一个允许您动态创建属性的类。
答案 2 :(得分:4)
这是我在dict
和object
之间决定存储简单,无方法键值对的方法:
dict
dict
dict
dict
object
了解dis
显示的差异可能也很有趣:
>>> def dictf(d):
... d['apple'] = 'red'
... return d['apple']
...
>>> def objf(ob):
... ob.apple = 'red'
... return ob.apple
...
>>> dis.dis(dictf)
2 0 LOAD_CONST 1 ('red')
3 LOAD_FAST 0 (d)
6 LOAD_CONST 2 ('apple')
9 STORE_SUBSCR
3 10 LOAD_FAST 0 (d)
13 LOAD_CONST 2 ('apple')
16 BINARY_SUBSCR
17 RETURN_VALUE
>>> dis.dis(objf)
2 0 LOAD_CONST 1 ('red')
3 LOAD_FAST 0 (ob)
6 STORE_ATTR 0 (apple)
3 9 LOAD_FAST 0 (ob)
12 LOAD_ATTR 0 (apple)
15 RETURN_VALUE
答案 3 :(得分:3)
stuff.a
你真正访问
stulff.__dict__['a']
同样,您可以将dict
子类化,使__getattr__
返回与__getitem__
相同的位置,因此stuff.a
也适用于您的dict
子类。
当您知道映射中的键都是有效Python标识符的简单字符串时,对象方法通常既方便又有用。如果你有更复杂的键,那么你需要一个“真正的”映射。
当您需要的不仅仅是简单的映射时,您当然也应该使用对象。这个“更多”通常是返回值的额外状态或额外计算。
您还应该考虑其他人如何使用您的stuff
对象。如果他们知道这是一个简单的dict
,那么他们也知道他们可以调用stuff.update(other_stuff)
等。如果你给他们一个对象,那就不那么清楚了。基本上:如果您认为他们需要像普通stuff
一样操纵dict
的键和值,那么您应该将其设为dict
。
至于最“pythonic”的方式,那么我只能说我见过图书馆使用这两种方法:
BeautifulSoup library解析HTML并向您发送一些非常动态的对象,其中属性和项目访问都具有特殊含义。
他们本可以选择回馈dict
个对象,但是每个对象都有很多额外的状态,因此使用真正的类非常有意义。
当然也有很多库只能回馈普通的dict
对象 - 它们是许多Python程序的基础。