具有索引的中文文章模板

1. 1.8 Collecting a Bunch of Named Items

集中一组命名的条目

Credit: Alex Martelli

1.1. 1.8.1 Problem

问题

You want to collect a bunch of items together, naming each item of the bunch, and you find dictionary syntax a bit heavyweight for the purpose.

你想把一组条目集在一起,命名它们中的每一项,并且你发现字典语法对于这样的目的来说确有点重了。

1.2. 1.8.2 Solution

解决

Any (classic) class inherently wraps a dictionary, and we take advantage of this:

任何(经典)类本来就包装了一个字典,我们可以利用这个:

   1 class Bunch:
   2     def _ _init_ _(self, **kwds):
   3         self._ _dict_ _.update(kwds)

Now, to group a few variables, create a Bunch instance:

现在,为了集中一些变量,建立一个Bunch实例:

   1 point = Bunch(datum=y, squared=y*y, coord=x)

You can access and rebind the named attributes just created, add others, remove some, and so on. For example:

你能够访问和重新绑定刚刚被建立,命名的属性,增加其他的,移除一些等。例如:

   1 if point.squared > threshold:
   2     point.isok = 1

1.3. 1.8.3 Discussion

讨论

Often, we just want to collect a bunch of stuff together, naming each item of the bunch; a dictionary's okay for that, but a small do-nothing class is even handier and is prettier to use.

经常地,我们仅仅想把一组元素集中在一起,为他们每一个命名。一个字典能够胜任它,但是一个小型的什么也不做的类更方便,更利于使用

A dictionary is fine for collecting a few items in which each item has a name (the item's key in the dictionary can be thought of as the item's name, in this context). However, when all names are identifiers, to be used just like variables, the dictionary-access syntax is not maximally clear:

集中一些元素,让每个元素都有一个名字,这对于字典来说不是难事(在这个上下文中,字典里元素的键能够被考虑作为元素的名字)。然而,当所有名字是标识符的时候,能够象变量一样被使用,访问字典的语法不在是非常清晰的了。

   1 if point['squared'] > threshold

It takes minimal effort to build a little class, as in this recipe, to ease the initialization task and provide elegant attribute-access syntax:

花费更小的代价构造一个很小的类,就象在这个配方里, 更容易初始化任务并提供优雅的属性访问语法:

   1 if bunch.squared > threshold

An equally attractive alternative implementation to the one used in the solution is:

一个同样有吸引力的可选择的实现在下列解决方案中被使用:

   1 class EvenSimplerBunch:
   2     def _ _init_ _(self, **kwds): self._ _dict_ _ = kwds

The alternative presented in the Bunch class has the advantage of not rebinding self._ _dict_ _ (it uses the dictionary's update method to modify it instead), so it will keep working even if, in some hypothetical far-future dialect of Python, this specific dictionary became nonrebindable (as long, of course, as it remains mutable). But this EvenSimplerBunch is indeed even simpler, and marginally speedier, as it just rebinds the dictionary.

在选择的Bunch类里表示有一个好处,不用重新绑定self._ _dict_ _(取而代之的是它使用字典的update方法去更改它)。所以它将继续工作,即使,在一些假定python遥远未来的方言中,这个特殊的字典变得不可绑定时(当然,只要它仍然可变)但是当它仅仅重绑定字典的时候EvenSimplerBunch确实很简单,并且更快。

It is not difficult to add special methods to allow attributes to be accessed as bunch['squared'] and so on. In Python 2.1 or earlier, for example, the simplest way is:

增加特殊的方法来允许属性被作为bunch['squared']来访问不是很困难。在Python2.1或更早版本,例如,最简单的方法是:

   1 import operator
   2 class MurkierBunch:
   3     def _ _init_ _(self, **kwds):
   4         self._ _dict_ _ = kwds
   5     def _ _getitem_ _(self, key):
   6         return operator.getitem(self._ _dict_ _, key)
   7     def _ _setitem_ _(self, key, value):
   8         return operator.setitem(self._ _dict_ _, key, value)
   9     def _ _delitem_ _(self, key):
  10         return operator.delitem(self._ _dict_ _, key)

In Python 2.2, we can get the same effect by inheriting from the dict built-in type and delegating the other way around:

在Python 2.2,我们能通过继承从字典内建类型得到相同的效果并且委托周围的其他方法:

   1 class MurkierBunch22(dict):
   2     def _ _init_ _(self, **kwds): dict._ _init_ _(self, kwds)
   3     _ _getattr_ _ = dict._ _getitem_ _
   4     _ _setattr_ _ = dict._ _setitem_ _
   5     _ _delattr_ _ = dict._ _delitem_ _

Neither approach makes these Bunch variants into fully fledged dictionaries. There are problems with each梖or example, what is someBunch.keys supposed to mean? Does it refer to the method returning the list of keys, or is it just the same thing as someBunch['keys']? It's definitely better to avoid such confusion: Python distinguishes between attributes and items for clarity and simplicity. However, many newcomers to Python do believe they desire such confusion, generally because of previous experience with JavaScript, in which attributes and items are regularly confused. Such idioms, however, seem to have little usefulness in Python. For occasional access to an attribute whose name is held in a variable (or otherwise runtime-computed), the built-in functions getattr, setattr, and delattr are quite adequate, and they are definitely preferable to complicating the delightfully simple little Bunch class with the semantically murky approaches shown in the previous paragraph.

两种方法都不能使这些Bunch变量制造成完全的字典。每个方法或者例子都有问题, someBunch.keys的假设意味着什么?它引用返回键列表的方法,或者仅仅和someBunch['keys']相同吗?它明显更好的避免那样的混淆:为了清楚和简单,python区分属性和条目。然而,许多python新手相信他们期望那样的混淆,一般是因为以前JavaScript的经验。在JavaScript中,属性和条目被有规律的混淆。然而,那样的习惯用法似乎在python里没有什么用。为了偶然访问一个名字在变量里的属性(或者另外运行时的计算),内建的函数,getattr, setattr, 和delattr是足够了。对于显示在前面带有晦涩语义复杂化优美简单的小Bunch类的方法而言,他们是更优越的。

1.4. 1.8.4 See Also

参考

The Tutorial section on classes.