1. 程式人生 > >5.3.5 namedtuple() 建立命名欄位的元組結構

5.3.5 namedtuple() 建立命名欄位的元組結構

在命名元組裡,給每個元組的位置新增一個名稱,並且可以通過名稱來訪問,大大地提高可讀性,以便寫出清晰程式碼,提高程式碼的維護性。其實它就像C++裡的結構體。

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

返回一個新型別名稱typenname的元組。引數field_names是一個字串表示的元素名稱,每個欄位之間可以通過空格、逗號方式來分隔,比如’x y’,’x, y’。另外也可以採用列表的方式,比如[‘x’, ‘y’]。在欄位名稱命名上需要注意的是每個欄位要是有效的python識別符號規則,同時不能是

python關鍵字,另外不要以下劃線或數字開頭。

如果引數renameTrue就會自動地把不合法名稱轉換為相應合法的名稱,比如:['abc', 'def', 'ghi', 'abc']轉換為['abc', '_1', 'ghi', '_3'],在這裡把def轉換_1,同時把重複的abc轉換_3

如果引數verboseTrue就會自動列印_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 深圳