IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [原]5.3.5 namedtuple() 创建命名字段的元组结构

    caimouse发表于 2016-01-10 21:39:14
    love 0

    在命名元组里,给每个元组的位置添加一个名称,并且可以通过名称来访问,大大地提高可读性,以便写出清晰代码,提高代码的维护性。其实它就像C++里的结构体。

    collections.namedtuple(typename, field_names, verbose=False, rename=False) 

    返回一个新类型名称typenname的元组。参数field_names是一个字串表示的元素名称,每个字段之间可以通过空格、逗号方式来分隔,比如’x y’,’x, y’。另外也可以采用列表的方式,比如[‘x’, ‘y’]。在字段名称命名上需要注意的是每个字段要是有效的python标识符规则,同时不能是python关键字,另外不要以下划线或数字开头。

    如果参数rename为True就会自动地把不合法名称转换为相应合法的名称,比如:['abc', 'def', 'ghi', 'abc']转换为['abc', '_1', 'ghi', '_3'],在这里把def转换_1,同时把重复的abc转换_3。

    如果参数verbose为True就会自动打印_source属性。

    例子:

    #python 3.4

    import collections

     

    Point = collections.namedtuple('Point', 'x, y, z')

    p1 = Point(30, 40, 50)

    print(p1)

    print(p1[0] + p1[1] + p1[2])

    x, y, z = p1

    print(x, y, z)

    print(p1.x, p1.y, p1.z)

    结果输出如下:

    Point(x=30, y=40, z=50)

    120

    30 40 50

    30 40 50

     

    classmethod somenamedtuple._make(iterable)

    从已经存在迭代对象或者序列生成一个新的命名元组。

    例子:

    #python 3.4

    import collections

     

    Point = collections.namedtuple('Point', 'x, y, z')

    t = [10, 20, 30]

    p1 = Point._make(t)

    print(p1)

    结果输出如下:

    Point(x=10, y=20, z=30)

     

    somenamedtuple._asdict() 

    把命名元组生成一个新的OrderedDict对象返回,可以使用内置函数vars()实现相应的功能。

    例子:

    #python 3.4

    import collections

     

    Point = collections.namedtuple('Point', 'x, y, z')

    t = [10, 20, 30]

    p1 = Point._make(t)

    print(p1._asdict())

    print(vars(p1))

    结果输出如下:

    OrderedDict([('x', 10), ('y', 20), ('z', 30)])

    OrderedDict([('x', 10), ('y', 20), ('z', 30)])

     

    somenamedtuple._replace(kwargs) 

    对指定的字段的值进行替换,并返回新的命名元组。

    例子:

    #python 3.4

    import collections

     

    Point = collections.namedtuple('Point', 'x, y, z')

    t = [10, 20, 30]

    p1 = Point._make(t)

    print(p1._replace(x=100))

    print(vars(p1))

    结果输出如下:

    Point(x=100, y=20, z=30)

    OrderedDict([('x', 10), ('y', 20), ('z', 30)])

     

    somenamedtuple._source 

    返回创建命名元组相关的python代码字符串。可以把它打印出来,或者使用exec()函数执行,或者输出到文件里,再给别的代码导入。

    例子:

    #python 3.4

    import collections

     

    Point = collections.namedtuple('Point', 'x, y, z')

    t = [10, 20, 30]

    p1 = Point._make(t)

    print(p1._source)

    输出结果如下:

    from builtins import property as _property, tuple as _tuple

    from operator import itemgetter as _itemgetter

    from collections import OrderedDict

     

    class Point(tuple):

        'Point(x, y, z)'

     

        __slots__ = ()

     

        _fields = ('x', 'y', 'z')

     

        def __new__(_cls, x, y, z):

            'Create new instance of Point(x, y, z)'

            return _tuple.__new__(_cls, (x, y, z))

     

        @classmethod

        def _make(cls, iterable, new=tuple.__new__, len=len):

            'Make a new Point object from a sequence or iterable'

            result = new(cls, iterable)

            if len(result) != 3:

                raise TypeError('Expected 3 arguments, got %d' % len(result))

            return result

     

        def _replace(_self, **kwds):

            'Return a new Point object replacing specified fields with new values'

            result = _self._make(map(kwds.pop, ('x', 'y', 'z'), _self))

            if kwds:

                raise ValueError('Got unexpected field names: %r' % list(kwds))

            return result

     

        def __repr__(self):

            'Return a nicely formatted representation string'

            return self.__class__.__name__ + '(x=%r, y=%r, z=%r)' % self

     

        @property

        def __dict__(self):

            'A new OrderedDict mapping field names to their values'

            return OrderedDict(zip(self._fields, self))

     

        def _asdict(self):

            'Return a new OrderedDict which maps field names to their values.'

            return self.__dict__

     

        def __getnewargs__(self):

            'Return self as a plain tuple.  Used by copy and pickle.'

            return tuple(self)

     

        def __getstate__(self):

            'Exclude the OrderedDict from pickling'

            return None

     

        x = _property(_itemgetter(0), doc='Alias for field number 0')

     

        y = _property(_itemgetter(1), doc='Alias for field number 1')

     

        z = _property(_itemgetter(2), doc='Alias for field number 2')

     

     

    somenamedtuple._fields 

    返回命名元组的字段列表。可以用于从已经创建命名元组组合产生新的元组。

    例子:

    #python 3.4

    import collections

     

    Point = collections.namedtuple('Point', 'x, y, z')

    print(Point._fields)

    Point4 = collections.namedtuple('Point4', Point._fields + ('w',))

    print(Point4, Point4._fields)

    结果输出如下:

    ('x', 'y', 'z')

    <class '__main__.Point4'> ('x', 'y', 'z', 'w')

     

    使用命名元组从csv文件或者SQLite生成结构体信息保存:

    EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')

     

    import csv

    for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):

        print(emp.name, emp.title)

     

    import sqlite3

    conn = sqlite3.connect('/companydata')

    cursor = conn.cursor()

    cursor.execute('SELECT name, age, title, department, paygrade FROM employees')

    for emp in map(EmployeeRecord._make, cursor.fetchall()):

        print(emp.name, emp.title)

     

    从这个例子里,可以看到从csv文件读取之后,就可以函数map的运算,生成一个EmployeeRecord结构体记录了,这样可以把行记录转换相应的结构化的信息,就方便查找,排序等操作。

     

    使用命名元组作为基类继承:

    #python 3.4

    import collections

     

    class Point(collections.namedtuple('Point', 'x y')):

        __slots__ = ()

        @property

        def hypot(self):

            return (self.x ** 2 + self.y ** 2) ** 0.5

        def __str__(self):

            return 'Point: x=%6.3f  y=%6.3f  hypot=%6.3f' % (self.x, self.y, self.hypot)

    for p in Point(3, 4), Point(14, 5/7):

        print(p)

    结果输出如下:

    Point: x= 3.000  y= 4.000  hypot= 5.000

    Point: x=14.000  y= 0.714  hypot=14.018

     

    蔡军生 QQ:9073204 深圳



沪ICP备19023445号-2号
友情链接