Python 可通过属性名或索引选项访问的结构
我对Python非常陌生,并试图弄清楚如何创建一个对象,该对象的值可以通过属性名或索引访问。例如,os.stat()返回stat_结果的方式或pwd.getpwnam()返回struct_passwd的方式 在试图弄明白这一点时,我只遇到了上述类型的C实现。在Python中没有什么特别的东西。创建此类对象的Python本机方法是什么 如果这已经被广泛报道,我很抱歉。在寻找答案的过程中,我肯定遗漏了一些基本概念,这些概念使我无法找到答案 Python 2.6的引入使这一过程变得简单。对于较旧的Python版本,您可以使用 直接从文件中引用:Python 可通过属性名或索引选项访问的结构,python,data-structures,namedtuple,Python,Data Structures,Namedtuple,我对Python非常陌生,并试图弄清楚如何创建一个对象,该对象的值可以通过属性名或索引访问。例如,os.stat()返回stat_结果的方式或pwd.getpwnam()返回struct_passwd的方式 在试图弄明白这一点时,我只遇到了上述类型的C实现。在Python中没有什么特别的东西。创建此类对象的Python本机方法是什么 如果这已经被广泛报道,我很抱歉。在寻找答案的过程中,我肯定遗漏了一些基本概念,这些概念使我无法找到答案 Python 2.6的引入使这一过程变得简单。对于较旧的Py
>>> 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)
具有可通过属性名或索引访问的值的对象
我不知道你觉得这有什么困难
索引可访问的集合实现了\uu getitem\uu
可通过名称访问的集合实现了\uuuuu getattr\uuuuu
(或\uuuuuu getattribute\uuuuu
)
您可以毫不费力地实现这两个功能。或者,您可以使用namedtuple
为了使生活更简单,您可以扩展tuple
类,这样就不必实现自己的\uuu getitem\uuuu
。或者,您可以定义一个普通类,该类也具有\uuuuuGetItem\uuuuuuu
,这样您就不必处理\uuuuuuuuGetAttr\uuuuuuuu
比如说
>>> 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
不能使用与os.stat()和其他对象的结果对象相同的实现。然而,Python2.6有一个新的工厂函数,它创建了一个类似的数据类型,称为命名元组。命名元组是其插槽也可以通过名称寻址的元组。根据文档,命名元组不需要比常规元组更多的内存,因为它们没有每个实例的字典。工厂功能签名为:
collections.namedtuple(typename, field_names[, verbose])
第一个参数指定新类型的名称,第二个参数是包含字段名的字符串(空格或逗号分隔),最后,如果verbose为true,则工厂函数还将打印生成的类
示例
假设您有一个包含用户名和密码的元组。要访问用户名,您将在位置0处获取项目,并在位置1处访问密码:
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
如果您对新创建的凭证类型的代码外观感兴趣,可以在创建类型时将verbose=True添加到参数列表中,在这种特殊情况下,我们会得到以下输出:
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()函数,该函数有助于从序列或iterable创建凭证实例。例如:
cred_tuple = ('joeuser', 'secret123')
credential = Credential._make(cred_tuple)
namedtuple的python库文档包含更多信息和代码示例,因此我建议您