我對Python非常陌生,並試圖找出如何創建具有可通過屬性名稱或索引訪問的值的對象。例如,os.stat()返回一個stat_result的方式,或者pwd.getpwnam()返回一個struct_passwd。可通過屬性名稱或索引選項訪問的結構
在試圖弄清楚,我只遇到了上述類型的C實現。沒有什麼特別的Python。什麼是Python原生的方式來創建這種類型的對象?
我很抱歉,如果這已被廣泛覆蓋。在尋找答案時,我必須錯過一些基本概念,即排除我找到答案。
我對Python非常陌生,並試圖找出如何創建具有可通過屬性名稱或索引訪問的值的對象。例如,os.stat()返回一個stat_result的方式,或者pwd.getpwnam()返回一個struct_passwd。可通過屬性名稱或索引選項訪問的結構
在試圖弄清楚,我只遇到了上述類型的C實現。沒有什麼特別的Python。什麼是Python原生的方式來創建這種類型的對象?
我很抱歉,如果這已被廣泛覆蓋。在尋找答案時,我必須錯過一些基本概念,即排除我找到答案。
不能使用相同的實現爲os.stat()和其他人的結果對象。然而Python 2.6有一個新的工廠函數,它創建一個名爲元組的類似數據類型。一個命名的元組是一個元組,其插槽也可以通過名稱來尋址。根據文檔,指定的元組不應該要求更多的內存,因爲它們沒有每個實例字典。工廠功能簽名是:
collections.namedtuple(typename, field_names[, verbose])
第一個參數指定的新類型的名稱,第二個參數是一個字符串(空格或逗號分隔)包含的字段名稱和,最後,如果詳細爲真,則工廠功能也將打印生成的類。
例
假設你有一個包含用戶名和密碼的元組。在零位訪問你獲得該項目的用戶名和密碼在一個位置訪問:
credential = ('joeuser', 'secret123')
print 'Username:', credential[0]
print 'Password:', credential[1]
沒有什麼不對的代碼,但元組是不是自我記錄。您必須查找並閱讀關於元組中字段定位的文檔。這是指定的元組可以救援的地方。我們可以重新編碼在前面的例子如下:
import collections
# Create a new sub-tuple named Credential
Credential = collections.namedtuple('Credential', 'username, password')
credential = Credential(username='joeuser', password='secret123')
print 'Username:', credential.username
print 'Password:', credential.password
如果你有興趣的代碼如下所示爲新創建的證書類型,你可以在創建類型時添加詳細=真參數列表,在此特殊情況下,我們得到以下的輸出:
import collections
Credential = collections.namedtuple('Credential', 'username, password', verbose=True)
class Credential(tuple):
'Credential(username, password)'
__slots__ =()
_fields = ('username', 'password')
def __new__(_cls, username, password):
return _tuple.__new__(_cls, (username, password))
@classmethod
def _make(cls, iterable, new=tuple.__new__, len=len):
'Make a new Credential object from a sequence or iterable'
result = new(cls, iterable)
if len(result) != 2:
raise TypeError('Expected 2 arguments, got %d' % len(result))
return result
def __repr__(self):
return 'Credential(username=%r, password=%r)' % self
def _asdict(t):
'Return a new dict which maps field names to their values'
return {'username': t[0], 'password': t[1]}
def _replace(_self, **kwds):
'Return a new Credential object replacing specified fields with new values'
result = _self._make(map(kwds.pop, ('username', 'password'), _self))
if kwds:
raise ValueError('Got unexpected field names: %r' % kwds.keys())
return result
def __getnewargs__(self):
return tuple(self)
username = _property(_itemgetter(0))
password = _property(_itemgetter(1))
命名組不會只提供訪問通過名稱字段,但也包含輔助功能,如這有助於從一個序列或創建憑證實例_make()函數迭代。例如:
cred_tuple = ('joeuser', 'secret123')
credential = Credential._make(cred_tuple)
爲namedtuple Python庫文檔有更多的信息和代碼示例,所以我建議你take a peek.
Python 2.6引入了collections.namedtuple使這個很簡單。使用較舊的Python版本,您可以使用named tuple recipe。
從文檔直接引用:
>>> Point = namedtuple('Point', 'x y')
>>> p = Point(11, y=22) # instantiate with positional or keyword arguments
>>> p[0] + p[1] # indexable like the plain tuple (11, 22)
33
>>> x, y = p # unpack like a regular tuple
>>> x, y
(11, 22)
>>> p.x + p.y # fields also accessible by name
33
>>> p # readable __repr__ with a name=value style
Point(x=11, y=22)
具有可訪問或者通過屬性名稱或指數
我不知道你在做什麼值的對象在這方面發現很難。
索引可訪問的集合實現__getitem__
。
可通過名稱訪問的集合實現__getattr__
(或__getattribute__
)。
你可以在沒有任何麻煩的情況下實現。或者,您可以使用namedtuple
。
爲了使生活更簡單,您可以擴展tuple
類,以便您不必實施自己的__getitem__
。或者你可以定義一個普通類,它也有__getitem__
,所以你不必與__getattr__
混淆。
例如
>>> class Foo(object):
... def __init__(self, x, y, z):
... self.x= x
... self.y= y
... self.z= z
... def __getitem__(self, index):
... return { 0: self.x, 1: self.y, 2: self.z }[index]
...
>>> f= Foo(1,2,3)
>>> f.x
1
>>> f[0]
1
>>> f[1]
2
>>> f[2]
3
>>> f.y
2