Pythonic|collections.namedtuple的使用和对 list 对象Pythonic的的操作

collections

collections是Python内建的一个集合模块,提供了许多有用的集合类和方法。

可以把它理解为一个容器,里面提供Python标准内建容器 dict , list , set , 和 tuple 的替代选择。

namedtuple() : 创建一个命名元组子类的工厂函数
deque :    高效增删改双向列表,类似列表(list)的容器,实现了在两端快速添加(append)和弹出(pop)
defaultdict : 当字典查询时,为key不存在提供一个默认值。
OrderedDict : 有序词典,就是记住了插入顺序
Counter : 计数功能

namedtuple() 命名元组

namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)

参数

  • typename : 命名的名字,返回一个新的元组子类,名为 typename
  • field_names : 可以是一个[‘x’, ‘y’]这样的序列,也可以是’x, y’或者’x y’
  • rename :   python3.1添加,如果 rename 为真, 无效域名会自动转换成位置名。比如 [‘abc’, ‘def’, ‘ghi’, ‘abc’] 转换成 [‘abc’, ‘_1’, ‘ghi’, ‘_3’] , 消除关键词 def 和重复域名 abc 。
  • defaults :  python3.7添加, defaults 可以为 None 或者是一个默认值的 iterable(可迭代对象)。如果一个默认值域必须跟其他没有默认值的域在一起出现, defaults 就应用到最右边的参数。比如如果域名 [‘x’, ‘y’, ‘z’] 和默认值 (1, 2) ,那么 x 就必须指定一个参数值 ,y 默认值 1 , z 默认值 2 。
  • module :   python3.6添加,如果 module 值有定义,命名元组的 __module__属性值就被设置

 namedtuple使用


import collections
# 创建对象  我们定义了一个Point类型的包含x,y两个值的增强元祖类型
PointA = collections.namedtuple('Point', ['x', 'y'])
p = PointA(10, y=20)  # 可以使用关键字参数和位置参数初始化namedtuple
#注意这个p类型既是我们定义的Point也是tuple,而元祖是不可使用_make 赋值和_replace 更改值的
print(p)  # 直接打印 Point(x=10, y=20) 也可以获取单个内容 p.x p.y
p_list = [PointA(i, y=-i) for i in range(5)] #也可迭代生成一个list
print(p_list)  # [Point(x=0, y=0), Point(x=1, y=-1), Point(x=2, y=-2), Point(x=3, y=-3), Point(x=4, y=-4)]
print(len(p_list))  # 获取长度 5
print(p_list[0])  #  根据下标取  Point(x=0, y=0)
from random import choice

print(choice(p_list))  # 随机取一个
print(p_list[:3])  # 取前三个
print(p_list[0::2])  # 取第0个 然后每隔2个取一个

这是一些对list操作的特殊方法,是Python 自有的对序列数据类型的一些操作

[print(p_item) for p_item in reversed(p_list)]  # 反向排序输出

print(PointA("A", "B") in p_list)
print(PointA(0, 0) in p_list)
for p_item in sorted(p_list, key=lambda x: x.y):  #匿名函数 参数:算式表达式
    # 根据每个元素的y值排序,也可以写个函数自己定义一个,返回值根据返回值默认从小到大排
    print(p_item)

sorted() 函数对所有可迭代的对象进行排序操作。

sort 与 sorted 区别:

sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。

list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。

sorted(iterable, key=None, reverse=False)  

参数说明:

  • iterable -- 可迭代对象。
  • key -- 用来进行比较的元素,可以是一个函数,也可以是一个类,也可以是其他的处理方法。只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
  • reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。

返回值:

        返回重新排序的列表。

类中使用namedtuple

在类中使用 namedtuple 如果需要对这个类实例化的对象所有的对[]操作都操作到 类中定义的namedtuple  对象上,只需要在类中实现 __len__方法和__getitem__方法就好了

PointA = collections.namedtuple('Point', ['x', 'y'])
class PointList:
    def __init__(self):
        self._point = [PointA(i, y=-i) for i in range(5)]
    def __len__(self):   #上面列表推导式的 len函数本质就是这个len的实现
        return len(self._point)
    def __getitem__(self, position):  #上面后续其他对元素的操作 依赖于__getitem__
        # 也就是对这个类实例化对象的对[]的操作都给了self._point列表
        # 如[x]按下标取, random.choice,切片,迭代,sorted排序等
        return self._point[position]
point_list=PointList()
print(len(point_list))
print(collections.Counter(point_list))

优点是可以更加方便地利用 Python 的标准库,比如 random.choice 函
数,从而不用重新发明轮子。这都是由 __getitem__ 方法提供的 

好,我们这时候想打乱一下这个序列,我们知道有 random.shuffle 函
数可用

from random import shuffle
shuffle(point_list)

他会报错:TypeError: 'PointList' object does not support item assignment

('PointList' 对象不支持为元素赋值)。这个问题的原因是,shuffle 函数要调换集合中元素的位置,而 PointList只实现
了不可变的序列协议。可变的序列还必须提供 __setitem__ 方法。

class PointList:
    def __init__(self):
        self._point = [PointA(i, y=-i) for i in range(5)]
    def __len__(self):   #上面列表推导式的 len函数本质就是这个len的实现
        return len(self._point)
    def __getitem__(self, position):  #上面后续其他对元素的操作 依赖于__getitem__
        # 也就是对这个类实例化对象的对[]的操作都给了self._point列表
        # 如[x]按下标取, random.choice,切片,迭代,sorted排序等
        return self._point[position]
    def __setitem__(self, key, value):
        self._point[key]=value
point_list=PointList()
print(len(point_list))
# print(collections.Counter(point_list))

from random import shuffle
shuffle(point_list)
print(point_list[:3])

定义__setitem__函数,它的参数为 self、key和 value。我们对self的_point根据key取到的元素改value。现在可以打乱 point_list了,因为 PointList实现了可变序列协议所需的方法。

当然我们也可以定义一个方法,然后利用python动态语言的猴子特性,可以在外面直接赋值给PointList类的__setitem__属性

def set_point(p, key, value): 
    p._point[key] = value
PointList.__setitem__ = set_point

这里的关键是point_list对象有一个名为 _point的属性,而且 _point的值必须是可变序列。然后,我们实现特殊方法 __setitem__,从而把它依附到 PointList类上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值