流畅的python自学笔记(第二章)

流畅的python自学笔记(第二章)

数据结构嵌套元组拆包


# 函数里用*args获取不定量个数的参数,平行思想,可以用以下获取不想要的元组元素
*head, xyp1, xyp2 = range(5)
xyp3, *body, xyp4 = range(5)
xyp5, xyp6, *last = range(5)
# 结果就是,head,body,last是三个列表,其他都是一个int

具名元组


# 具名元组,顾名思义,我理解为具有名称的元组,算是一个class,type 'type'

# 创建具名元组格式  sth = ('name', 'xyp1 xyp2 xyp3 xyp4')

# 第一个元素是元组名字,第二个是可以是由数个字符串组成的可迭代对象,或者是由空格分隔的字符串

# 如上例子,每个字段的名称分别是xpy1, 2, 3, 4
from collections import namedtuple

City = namedtuple('city', 'name country poplution location')

beijing = City('beijing', 'China', '9999999', (123.45, 123.45))

print(beijing.name)

print(beijing.location)

切片

# 给切片赋值时,要确保等号右边是可迭代对象如
a_list = list(range(4))
a_list[2::2] = [3]
# a_list[2::1] = 3   错误示例
a_list[:3:2] = "a", "abc" # 也是可以的
# ============================================================================
# 建立列表中的列表,比如矩阵【[], [], []】
# 我个人习惯用列表推导,而不是[]*3这种方式,因为,如果‘[]’是某个变量
# 会有意想不到的错误产生,因为[]*3 是对[]的三次引用,指向同一个目标的
# 正确示例如下
right_list = [['_']*3 for i in range(3)]
right_list[1][2] = 'X'
print(right_list)
# result is [['_', '_', '_'], ['_', '_', 'X'], ['_', '_', '_']]

# 错误示例如下
wrong_list = [['_']*3]*3
wrong_list[1][2] = 'C'
print(wrong_list)
# result is [['_', '_', 'C'], ['_', '_', 'C'], ['_', '_', 'C']]
# ============================================================================

序列的增量赋值

# 个人理解就是,可变序列实现了就地加(乘)法,__iadd__,可以a += b
# 不可变序列不支持这样操作,比如元组等,只能a = a + b
# 区别就是,前者返回a原本的地址
# 后者则分两步操作,先进行a+b之后赋值给a,a的地址发生了变化

# 得到教训
# 1. 不要把可变序列放入元组
# 2. 增量赋值不是一个原子操作,(好像是分三步走)
# 3. python字节码很有用 (这条目前没啥感觉,可能以后会回来删掉这句话)

bisect模块

# 首先声明,两个主要函数insort和bisect都是用二分查找法来进行插入删除
# 使用的目的,是为了解决当list长度增大,list.index()查找效率下降的问题
# !!!被使用的列表,必须是一个有序地列表

# 我这里,分别写了递归二分查找,循环二分查找,index函数和bisect的效率比较
# 这里直接抄了这个大佬的代码https://www.cnblogs.com/beiluowuzheng/p/8452671.html
# 反正也不商用,就是自己写博客做个笔记,当作学习了,如果不可以,我删掉就好了

import random
from random import randint
from random import choice
import timeit

random.seed(5)
lst = [randint(1, 100) for _ in range(500000)]
lst.sort()
var = choice(lst)

def recursion_binary_research(lst, var, start, end):
	if start < end:
		return null
	mid = (start + end) // 2
	if var > lst[mid]:
		return recursion_binary_research(lst, var, mid, end)
	if var < lst[mid]:
		return recursion_binary_research(lst, var, start, mid)
	return mid
def loop_binary_research(lst, var):
	start, end = 0, len(lst) - 1
	while(start < end):
		mid = (start + end) // 2
		if val < lst[mid]:
			end = mid - 1
		elif val > lst[mid]:
			start = mid + 1
		else:
			return mid
	return None
def bisect_binary_research(lst, var):
	i = bisect.bisect(lst, var)
	if i != len(lst) and lst[i] == var:
		return i
	return None
# 说实话,我也不知道为什么不能下面直接调用recursion_binary_research,还要创建一个test
# 不过,我相信大佬,所以当作以后自己的规范了,只要用到时间性能测试,就这样创建一个测试函数

def test_recursion()
	return recursion_binary_search(lst, var, 0, len(lst)-1)
def test_loop()
	return loop_binary_research(lst, var)
def test_bisectt()
	return biest_binary_research(lst, var)

t1 = timeit.timeit("test_recursion()", setup="from __main__ import test_recursion")
t2 = timeit.timeit("test_loop()", setup="from __main__ import test_loop")
t3 = timeit.timeit("test_bisectt", setup="from __main__ import test_bisect")
# t3 的时间非常短,且远远短于直接用index()函数的时间

特定情况下可以替代列表的数据结构

# 数组
# 书中没有细讲
from array import array
from random import random
floats = array('d', (random() for i in range(10**7))) # 一个例子
# array('类型', [可以是列表],竟然也可以是个生成器)

双向队列

from collections import deque
dq = deque(range(10), maxlen=10)
dq.rotate(2) # 旋转操作,正数向右滚动,负数向左滚动
dq.appendleft(-1) # 队列左边加入-1,右边溢出一个数值 dq.append就是appendrightdq
dq.extend([1, 2, 3]) # 在右面加入三个值,会导致左边的三个数值溢出
dq.extendleft([1, 2, 3])

猜你喜欢

转载自blog.csdn.net/qq_40994221/article/details/108784903