美文网首页
collection.namedtuple用法以及所谓的Pyth

collection.namedtuple用法以及所谓的Pyth

作者: realnickman | 来源:发表于2019-04-08 04:56 被阅读0次

    Namedtuple,顾名思义就是为了方便使得tuple每一项都有实际的意义,如果你想建立一个简单的不想改变的且没有method的类(尤其是数据库读出来的数据),那么使用namedtuple就会特别方便。
    创建就用collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None),一个返回class的工厂方法。
    一些实用代码举例如下:

    from collections import namedtuple
    
    # nametuple: Factory Function for Tuples with Named Fields
    Person = namedtuple("Person", ["name","age", "sex"])
    p1 = Person("Jason", 30, sex = "Man")
    p2 = Person("Merry", 60, sex = "Woman")
    print("person's information:", p1.name, p1.age, p1.sex)
    print(p2)
    

    输出如下:

    person's information: Jason 30 Man
    Person(name='Merry', age=60, sex='Woman')
    

    三个自带方法分别是_asdict(),_replace() 和 _make

    # unpacking like a regular tuple
    name, age, sex = p1
    print("unpacking:", name, age, sex)
    
    # New an OrderedDict
    mydict = p1._asdict()
    print("OrderDict:", mydict.get("name"), mydict.get("age"), mydict.get("sex"))
    
    # Return a new instance of the named tuple
    new_person = p1._replace(name = "Kitty", age = 1, sex = "Woman")
    print(new_person)
    
    # make new instances with existing iterables
    p3 = Person._make(["Kobe",38, "Man"])
    print("_make an instance:",p3)
    

    输出:

    unpacking: Jason 30 Man
    OrderDict: Jason 30 Man
    Person(name='Kitty', age=1, sex='Woman')
    _make an instance: Person(name='Kobe', age=38, sex='Man')
    

    几种常用用法

    1. 把dict转为namedtuple

    mydict2 = {"name": "X", "age": 30, "sex": "Woman"}
    print("Dict to namedtuple:", Person(**mydict2))
    

    输出:

    Dict to namedtuple: Person(name='X', age=30, sex='Woman')
    

    2. 获取csv或者sqlite3的数据文件中的记录,使用_make()以及map()方法,然后iterate就可以了

    print("\nRead csv file 'users.csv':")
    import csv
    Name = namedtuple("Name", ["first","last"])
    for nm in map(Name._make, csv.reader(open("users.csv"))):
        print(nm.first,nm.last)
    
    print("\nConnect sqlite3  file 'my_friends.db':")
    import sqlite3
    conn = sqlite3.connect('my_friends.db')
    cursor = conn.cursor()
    cursor.execute('select * from friends where closeness > 700 order by closeness')
    Friend = namedtuple("Friend", ["first",'last','closeness'])
    for frd in map(Friend._make, cursor.fetchall()):
        print(frd.first,frd.last,frd.closeness)
    

    CSV输出:

    Read csv file 'users.csv':
    First Name Last Name
    Grace Hopper
    Alan Turing
    

    SQLITE3输出:

    Connect sqlite3  file 'my_friends.db':
    niubi Gong 777
    shenye Gong 888
    Yeye Gong 999
    zong Gong 999
    

    后面还看到了一个在Fluent Python这本书里面很好的一个例子,不仅仅讲了namedtuple 在创造“小类”方面的精妙用法,还顺便给出了重载dunder methods的优势。比如我们需要创建一个类表示一堆牌,那么其中每一张就是单独的一个card, 有两个属性,大小和点数。那么这个card就非常适合用namedtuple.

    Card = namedtuple("Card",['rank',"suit"])
    class ClassicDeck():
        ranks = [str(n) for n in range(2,11)] + list("JQKA")
        suits = "spades diamonds clubs heart".split()
    
        def __init__(self):
            self._cards = [Card(rank,suit) for rank in self.ranks for suit in self.suits]
    
        def __len__(self):
            return len(self._cards)
    
        def __getitem__(self, pos): 
            return self._cards[pos]
    
    deck = ClassicDeck()
    print(deck[2])
    print(len(deck))
    print(deck[2:6])
    from random import choice
    print("random:",choice(deck))
    
    # print out last 8 cards
    i = 8
    for card in reversed(deck):
        if i > 0:
            print(card)
            i = i-1
        else:
            break 
    

    其中精妙之处在于,"__getitem__"使得使用“collections[index]”获取元素成为可能,不仅如此,还让deck完全成为了一个iterable,可以执行slicing操作或者被iterate。 那么如果我要找一个随机的牌,按照传统用java写OOP的想法,本来是想在类里面写一个方法去产生随机牌,但是现在不需要了,直接用python库里面的函数random.choice()去做这个操作。 如果需要知道这堆牌的数量,原来还需要在类里面去写函数去执行,然后客户拿到类之后还需要记住是用deck.length() 或者deck.size() ,但是你直接重载dunder method __len__后,使用的时候直接拿len()就好了。这其实是一种非常pythonic的思想。

    相关文章

      网友评论

          本文标题:collection.namedtuple用法以及所谓的Pyth

          本文链接:https://www.haomeiwen.com/subject/tqsyiqtx.html