python高级编程(4) - 自定义序列类

自定义序列类

一,序列类型的分类

序列类型的分类

序列类型都能用 for 循环遍历

  • 第一分类
    1. 容器序列(能够放置任意类型的数据)
      • list,tuple,deque
    2. 扁平序列(只能放相同的数据类型)
      • str,bytes,bytearray,array.array
  • 第二分类
    1. 可变序列(能往对象添加数据)
      • list,deque,bytearray,array
    2. 不可变(不能往对象添加数据)
      • str,tuple,bytes

二,序列类型的abc继承关系

from collections import abc,从abc处进入序列的抽象基类,查看协议

abc 进入接口,观察抽象基类,我们发现实现一个序列类型需要实现的魔法方法

__contains__ 能够实现某个对象是否能使用 in 的操作,如果没有定义,直接定义了 __getitem__ 可以得到

三,序列类型中的+, +=和extend区别

l = [1, 2]
new_l = l + [3, 4, 5, 6]		①

l += [3, 4, 5, 6]				②
l += (3, 4, 5, 6)

l.entend([3, 4, 5])				③
l.entend(range(3))
l.entend('asdfg')

① 使用加号其实是把一个列表进行相加,不推荐使用,没有优化,速度慢

② 使用 += 操作,对象可以是任何可迭代对象,是在原来的列表上进项加,速度快,有优化,背后调用extend

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hHvTotZu-1592057542694)(assets/.png)]

extend : 接受任何可迭代对象,把对象的值一个一个迭代到列表里面

三,实现可切片的对象

  1. 只实现 __getitem__ 方法,就能进行切片的操作,使用其进行欺骗
class Group:
    # 支持切片的操作,实现序列协议
    def __init__(self, group_name, company_name, staffs):
        self.group_name = group_name
        self.company = company_name
        self.staffs = staffs    # 员工

    def __reversed__(self):
        pass

    def __getitem__(self, item):
        """
        实现欺骗的关键
        """
        print(item)
        return self.staffs[item]

    def __len__(self):
        pass

    def __iter__(self):
        pass

    def __contains__(self, item):
        pass


staffs = ['xyb1', 'xyb2', 'xyb3', 'xyb4']
group = Group(company_name='my_company', group_name='user', staffs=staffs)


print(group[::])
# 当对一个序列进行切片的时候,会自动转换成slice,slice(None, None, None)
  1. 不过要把序列协议实现完整,在 abc 抽象基类里面查看序列的魔法函数

    但是我们在开发当中往往需要对一个切出来的数据进行各种操作,应该继续维护切片出来的数据的类型

import numbers
class Group:
    # 支持切片的操作,实现序列协议
    def __init__(self, group_name, company_name, staffs):
        self.group_name = group_name
        self.company = company_name
        self.staffs = staffs    # 员工

    def __reversed__(self):
        self.staffs.reverse()

    def __getitem__(self, item):
        """
        实现欺骗的关键
        切片的原理:
            l = [1, 2, 3, 4, 5, 6]
            l[slice(0, 5, 1)]
        """
        cls = type(self)
        if isinstance(item, slice):
            print(666)
            return cls(self.group_name, self.company, self.staffs[item])
        elif isinstance(item, numbers.Integral):
            return cls(self.group_name, self.company, [self.staffs[item]])

    def __len__(self):
        return len(self.staffs)

    def __iter__(self):
        return (item for item in self.staffs)

    def __contains__(self, item):
        if item in self.staffs:
            return True
        else:
            return False


staffs = ['xyb1', 'xyb2', 'xyb3', 'xyb4']
group = Group(company_name='my_company', group_name='user', staffs=staffs)

s = group[2]
print(s.staffs)

优点:可以继续维护切片出来的数据,返回的是一个类,还能继续调用它的类的方法

四,bisect维护已排列序列

biset 能够维护一个有顺序的序列,在一个空列表中无须的加值,最后能够得到有序的列表

  • bisect 能够查看插入一个序列的时候应该从哪个位置插入,默认使用 bisect.right
import bisect
from collections import deque

# 用来 处理已排序的序列,用来维持已排序序列,升序
l = []
bisect.insort(l, 8)
bisect.insort(l, 5)
bisect.insort(l, 16)
bisect.insort(l, 7)
bisect.insort(l, 45)
bisect.insort(l, 0)
bisect.insort(l, 62)
bisect.insort(l, 123)

print(bisect.bisect(l, 158))    # 158应该在下表为8的地方插入
print(bisect.bisect_left(l, 123.0))    # 158应该在下表为8的地方插入
print(deque(l))
...
8
7
deque([0, 5, 7, 8, 16, 45, 62, 123])

五,什么时候我们不该使用列表

array 的效率很高,背后是一个 c 语言的数组

  1. 使用之前需要指定存储的数据类型(一个array只能储存一种数据类型)[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CmCtuKzz-1592057542696)(assets/.png)]

  2. import array    # array只能存放特点的数据类型
    a = list
    my_array = array.array('i')     # 申明类型
    my_array.append(1)
    my_array.append(2)
    print(my_array)
    
  3. 他的处理效率比列表高,忒你情况下使用array比较合适

四,列表推导式,生成器推导式

  1. 列表推导式
    l = [str(i) for i in range(20) if i > 10]
    print(l)
    
  2. 生成器表达式
    l = (str(i) for i in range(20) if i > 10)
    print(l)
    
  3. 字典推导式
    d = {key: value for key, value in enumerate('abcdefg')}
    print(d)
    
  4. 集合推导式
    s = {key for key, _ in d.items()}
    print(s)
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值