2025-09-10:仓库迁移

This commit is contained in:
2025-09-10 16:12:45 +08:00
parent e0e49b0ac9
commit 3130e336a1
146 changed files with 4066 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
# 普通的序列分解方式
def normal_func(list):
# list是可迭代对象能够直接分解成多个元素
length = list.__len__()
length= 2
x, y = list
# 如果list长度和接数据的元素数量不匹配会造成错误
x, y, z = list
# 在知道元素顺序的情况下想要丢弃list中的某些元素可以用下划线来无视变量
_ ,y = list

View File

@@ -0,0 +1,25 @@
# 如果序列中存储的元素是可哈希的,那就可以使用集合与生成器解决
def dequpe(items):
seen = set()
for item in items:
if item not in seen:
yield item
seen.add(item)
# 如果序列里的元素是不可哈希的,比如字典这种东西,就要先转化为可哈希对象;
# 这里自定义的key函数就起到了给字典解包的作用
def dequpe(items, key):
seen = set()
for item in items:
val = item if key is None else key(item)
if val not in seen:
yield item
seen.add(val)
# 如果单纯的做不改变顺序的去重,直接转集合再转列表就行了
a = [1,5,2,1,9,1,5,10]
a = list(set(a))
print(a)

View File

@@ -0,0 +1,18 @@
items = [0,1,2,3,4,5,6]
# 我们可以使用内置的slice函数对切片进行命名,参数分别为start|stop|step
a = slice(2,6,2)
print(items[a])
print(a.start, a.stop, a.step)
# indeces方法可以帮我们把start和stop自动限制在序列长度内,并返回一个限制后的切片
s = "sukahelloworld"
# 上面那个可能看着不明显,但是下面这个看着就明显多了
# s = "suka"
print(a.indices(len(s)))
# 因为返回的是元组,所以要使用得先解包
for i in range(*a.indices(len(s))):
print(s[i])

View File

@@ -0,0 +1,24 @@
words = ["look", "into", "my", "eyes", "look", "into", "my", "eyes",
"the", "eyes", "the", "eyes", "the", "eyes", "not", "around", "the",
"eyes", "don't", "look", "around", "the", "eyes", "look", "into",
"my", "eyes", "you're", "under"]
# collect里面的Counter库可以帮我们计数
from collections import Counter
word_counts = Counter(words)
top_three = word_counts.most_common(3)
print(top_three)
# Counter的底层是一个字典,是一个DefaultDict,这里处于学习目的把它实现一遍
from collections import defaultdict
def counter(word_list):
counter = defaultdict(int)
for word in word_list:
counter[word] += 1
return counter
print(counter(words))

View File

@@ -0,0 +1,25 @@
# 我们有一个字典列表,想要按照字典里的某些键对列表进行排序
# 字典列表如下:
rows = [
{"fname":"Brian", "lname": "Jones", "uid":1003},
{"fname":"David", "lname": "Beazley", "uid":1002},
{"fname":"John", "lname": "Cleese", "uid":1001},
{"fname":"Big", "lname": "Jones", "uid":1004}
]
# 这时候用到itemgetter模块
from operator import itemgetter
# itemgetter的主要功能是通过可查询的标记进行数据获取;
# 下面分别根据fname和uid进行数据获取
rows_by_fname = sorted(rows, key=itemgetter("fname"))
rows_by_uid = sorted(rows, key=itemgetter("uid"))
print(rows_by_fname)
print(rows_by_uid)
# 当然itemgetter也能被lambda函数替代替代操作如下
rows_by_fname_v2 = sorted(rows, key= lambda row: row["fname"])
print(rows_by_fname_v2)

View File

@@ -0,0 +1,32 @@
# 众所周知对class这种原生不支持比较的对象直接进行比较会造成暴毙
# 我们但如果非比不可呢?比如这个东西:
class User:
def __init__(self,user_id):
self.user_id = user_id
def __repr__(self):
return "User({})".format(self.user_id)
# 这里有一个列表user
user = [User(23), User(3), User(99)]
# 如果这时候需要按照某个属性给这个列表排序那么直接sorted会报错
try:
sorted(user)
pass
except:
print("你看吧,报错了")
# 这里的原因是对象不能直接进行比较,所以想要排序只能按照对象里的某个属性
# 有两种解决方案:
sorted_list = sorted(user, key=lambda x: x.user_id)
print(sorted_list)
# 要么就用operator库里的attrgetter
from operator import attrgetter
sorted_list = sorted(user, key=attrgetter("user_id"))
print(sorted_list)
# 用这东西的好处和针对字典的itemgetter一样可以取多个字段
# sorted_list = sorted(user, key=attrgetter("user_id", "word_2", "word_3", ...))
# 同样的max和min这种有key参数的内建函数都能用这些东西折腾

View File

@@ -0,0 +1,39 @@
# 假如我们有一个记录需要进行分组
rows = [
{"address": "5412 N CLARK", "date": "07/01/2012"},
{"address": "5148 N CLARK", "date": "07/04/2012"},
{"address": "5800 E 58TH", "date": "07/02/2012"},
{"address": "2122 N CLARK", "date": "07/03/2012"},
{"address": "5645 N RAVENSWOOD", "date": "07/02/2012"},
{"address": "1060 W ADDISON", "date": "07/02/2012"},
{"address": "4801 N BROADWAY", "date": "07/01/2012"},
{"address": "1039 W GRANVILLE", "date": "07/04/2012"},
]
# 如果我们想按日期进行分组那itertools里的groupby会很好用
from operator import itemgetter
from itertools import groupby
# 因为groupby只能检查连续的项所以我们先对列表进行排序
rows.sort(key=itemgetter("date"))
print(rows)
# 然后我们进行分组操作:
for date, items in groupby(rows, itemgetter("date")):
print(date)
for i in items:
print(' ', i)
# groupby每次返回的是一个值分组名称和一个子迭代器组内数据
# 当然如果是单纯的分组,一键多值字典是个好东西
from collections import defaultdict
data = defaultdict(list)
for item in rows:
data[item["date"]].append(item)
print(data)
# 在不考虑内存开销的情况下这东西比先排序再groupby快

View File

@@ -0,0 +1,71 @@
# 比如我有一个列表
mylist = [1,4,-5,10,-7,2,3,-1]
# 最脑瘫的方法就是用列表推导式重新生成一遍
filted_list_b0 = [x for x in mylist if x > 0]
filted_list_s0 = [x for x in mylist if x < 0]
# print(filted_list_b0)
# 当然如果列表很大这样做会裂开因为列表推导式本质上是遍历会建立一份mylist的复制
# 这个时候我们可以用生成器的方式表达解析结果以节省内存
filted_list_b0 = (x for x in mylist if x > 0)
# for i in filted_list_b0:
# print(i)
# 当然有的列表比较抽象:
mylist_suka = ['1', '2', '-3', '-', '4', 'N\A', '5']
# 这个时候我们可以先写逻辑进行过滤:
def drop_suka(val):
try:
x = int(val)
return True
except ValueError:
return False
# 然后我们用内建的filter函数进行过滤
# 第一个位置是一个值判断布尔函数,第二个参数是要过滤的列表,布尔函数里写过滤逻辑;
# filter返回一个迭代器所以可以直接用list方法转成列表
my_nonsuka_list = list(filter(drop_suka, mylist_suka))
# print(my_nonsuka_list)
# 列表推导式和生成器推导式都可以在值的位置进行:
# 1.计算 x*2
# 2.三元判断 x*2 if x < 1 else x
filted_list_b0 = [x*2 if x < 1 else x for x in mylist if x > 0]
filted_list_b0 = (x*2 if x < 1 else x for x in mylist if x > 0)
# 如果要筛选的元素在另一个列表里怎么办?比如我们有:
rows = [
"5412 N CLARK",
"5148 N CLARK",
"5800 E 58TH",
"2122 N CLARK",
"5645 N RAVENSWOOD",
"1060 W ADDISON",
"4801 N BROADWAY",
"1039 W GRANVILLE",
]
counts = [0,3,10,4,1,7,6,1]
# counts表示rows里面对应元素出现的次数如果我们想找count>5的元素咋整
# 1.搞一个布尔列表,告诉程序谁才是我们要的
wanted = [n > 5 for n in counts] # 这和[n for n in counts if n > 5]不一样,之前是在for的同时筛选,现在是for完看看是否符合n>5
# print(wanted)
# 2.用itertools的compress函数来进行对比
from itertools import compress
# itertools里的compress函数输入一个列表和一个布尔列表,返回一个迭代器,里面是列表中同样位置在布尔列表里为True的元素
result = list(compress(rows, wanted))
print(result)

View File

@@ -0,0 +1,19 @@
# 假如我们有一个字典,需要提取子集:
price = {
"ACME": 45.23,
"AAPL": 612.78,
"IBM": 205.55,
"HPQ": 37.2,
"FB": 10.75
}
# 直接用字典推导式
p1 = {key :value for key, value in price.items() if value > 200}
# 提取key也是
keys = {"AAPL", "IBM", "HPQ", "MSFT"}
p2 = {key : value for key, value in price.items() if key in keys}
# 字典推导式是最快的方法,比下面两个办法都快:
dict((key, value) for key, value in price if value > 100) # 快两倍
{key:price[key] for key in price.keys() if key in price.keys() & keys} # 快1.6倍

View File

@@ -0,0 +1,37 @@
# collection库中有一个东西叫做namedtuple,有点像结构体,可以给元组中的元素起名
from collections import namedtuple
Subscribe = namedtuple('Subscriber', ["addr", "joined"])
sub = Subscribe("suka@qq.com", "2024/07/17")
print(sub)
print(sub.addr)
print(sub.joined)
# 可以看到,这个东西和对象有点相似,但这种操作又保留了适用于元组的所有操作,比如索引和分解
print(sub[0])
print(len(sub))
addr, joined = sub
print(addr, joined)
# 如果我们获取的数据总是list类型,不是标准的json数据,那这东西就很有用
# 比如返回的数据是这种东西: data = [0,1,1,3,2,6]
# 如果是这种非标数据,普通代码处理长这样:
def compute_cost(records):
total = 0.0
for rec in records:
total += rec[1] * rec[2]
return total
# 这造成一个问题,鬼知道rec[1]和rec[2]是什么东西,代码可读性很傻逼;
# 所以我们可以在拿到数据的时候先标准化一下
Stock = namedtuple("Stock", ['name', 'share', 'price'])
def compute_cost(records):
total = 0.0
for rec in records:
stock = Stock(*rec)
total += stock.share * stock.price
return total
# 当然如果返回的已经是对象了,那就没有做namedtuple的必要了,在不想用类的时候可以用这东西替代字典

View File

@@ -0,0 +1,30 @@
# 这是一种简化操作,可以将转换和换算合为一体,比如我们有一个列表
nums = [1,2,3,4,5]
# 计算平方和我们一般这样子做:
nums_square = [x*x for x in nums]
s = sum(nums_square)
# 这个时候我们就可以这样来简化一下运算:
s = sum(x*x for x in nums)
# 又或者我们要在一堆参数中间加一些分隔符:
# 注意,这里的join和os.path.join不一样,这里是用来给jion输入的列表加分隔符的
s = ("ACME", 50, 123.45)
print(','.join(str(x) for x in s))
# 这里我们将生成器表达式从()里薅出来,当作可迭代参数塞进了函数里,这样避免了列表生成器造成的内存浪费
# 对单个字典内,我们用键值反转的方法来找元素,但是如果这是一个字典列表,那情况就大大不同了
portfolio = [
{'name': 'GOOG', 'shares': 50},
{'name': 'YHOO', 'shares': 75},
{'name': 'AOL', 'shares': 20},
{'name': 'SCOX', 'shares': 65}
]
max_share = max(portfolio, key=lambda x: x["shares"])
print(max_share)
# 当然如果仅仅只要拿到最小值就用到了生成器表达式内嵌的方法
max_share_num = max(s['shares'] for s in portfolio)
print(max_share_num)

View File

@@ -0,0 +1,36 @@
# 可迭代对象分解
def iterable_breakdown(list):
# 如果可迭代对象长度大于接数据的变量数量,分解值过多报错
length = list.__len__()
length = 20
# 这样会报错因为list长度是20但分解变量只有两个
x, y = list
# 想要接住任意长度的列表,需要用*
# *x是包含list前n-1个元素的列表y是最后一个元素
# 我们可以在任意位置接入带*的参数来接住一些值,这些值会在*变量中以列表存储
*x, y = list
x, *y, z = list
# 假设有一个变长元组序列
record = [("foo",1,2),("bar","suka"),("foo",2,4)]
def do_foo(x,y):
print(x,y)
def do_bar(s):
print(s)
# 我们可以使用*来解包从而将参数薅出来
for tag, *args in record:
if tag == "foo":
do_foo(*args)
elif tag == "bar":
do_bar(*args)
# 同理,也可以用*变量来占位挖掉不要的变量,比如在特定位置用*ignore或*_来挖掉参数

View File

@@ -0,0 +1,57 @@
# 假如又两个字典:
a = {"x":1, "z":3}
b = {"y":2, "z":4}
# 怎么将这两个字典映射到一个新字典里呢?愚蠢的办法是使用字典合并
# 这个方法会把右边的b刷写到a里
c = a|b
print(c)
# 但是,你会发现,如果原字典被改了,那c不会有变化:
a["x"] = 2
print(c)
# 这个时候使用映射方案的chainmap就会很好用
from collections import ChainMap
c = ChainMap(a,b)
print(",".join(str(x) for x in [c['x'], c['y'], c['z']]))
print(len(c))
# 如果此时更改原字典的值:
a["x"] = 1
# 输出也跟着更改了
print(",".join(str(x) for x in [c['x'], c['y'], c['z']]))
print(len(c))
# 注,chainmap中如果有重复的键,则会采用左值,比如上面的例子使用a["z"]作为重复键z的取值;
# 如果修改字典值,也会作用在左值上
del c["z"]
print(",".join(str(x) for x in [c['x'], c['y'], c['z']]))
print(a, b)
# 如果尝试删除a里已经没有但b里有的键,那么会报错
try:
del c["z"]
except:
print("在a里没找到键")
# 这东西的底层其实是一个链表,演示如下:
dic = ChainMap()
dic["x"] = 1
dic = dic.new_child()
print(dic)
dic["x"] = 2
dic = dic.new_child()
print(dic)
dic["x"] = 3
print(dic)
# 从这里我们开始回溯历史
dic = dic.parents
print(dic)
dic = dic.parents
print(dic)
dic = dic.parents
print(dic)
# 可以看到我们用new_child()函数创建了一个新节点用parents属性来回溯

View File

@@ -0,0 +1,19 @@
# 队列可以对最后N个元素进行保存
from collections import deque
# 从历史记录列表history得到length条最新历史记录
def latest_history(history, length):
window = deque(maxlen=length)
for record in history:
window.append(record)
# window引用双头队列组件deque,该组件有方法如下
# 从队尾加入
window.append(1)
# 从队尾弹出
window.pop()
# 从队头加入
window.appendleft(1)
# 从队头弹出
window.popleft()

View File

@@ -0,0 +1,33 @@
import heapq
# heapq里有两个函数nlargest和nsmallest可以找最大N个和最小N个
# 参数接受一个列表和一个N
def max_n(search_list, n):
list_max_n = heapq.nlargest(n ,search_list)
return list_max_n
def min_n(search_list, n):
list_min_n = heapq.nsmallest(n, search_list)
return list_min_n
# 这两个函数都提供了一个key输入来实现在字典列表中的应用
def max_in_dictlist(search_list, n, key):
max_key_n = heapq.nlargest(n, search_list, key=lambda dic : dic[key])
return max_key_n
# 如果寻找最大N个和最小N个元素这个方法在N的规模不大的时候好用
# 当日在N=1的时候还是用max和min方法更快要是N巨大那就得排序了
# heapq事实上是一个堆方法将列表在底层序列化为一个最小堆
def heapq_func():
ori_list = [1,2,3,4,5]
heap = list(ori_list)
# 将列表进行堆排序
heapq.heapify(heap)
# 弹出堆顶元素
heapq.heappop(heap)
if __name__ == '__main__':
l = [1,2,3,4,5]
print(max_n(l, 3))

View File

@@ -0,0 +1,43 @@
import heapq
# 优先级队列(使用小根堆实现)
class PriorityQueue:
def __init__(self):
self._queue = []
# 由于优先级在比较大小时可能相同造成比较失败维护一个下标index来进行二级辨识
self._index = 0
# 由于heapq的原理是生成一个小根堆所以优先级取负这样优先级越大堆识别到的优先级越小引入index在优先级相同时比较入栈先后顺序
def push(self, item, priority):
heapq.heappush(self._queue, (-priority, self._index, item))
self._index += 1
# 弹出堆顶值
def pop(self):
return heapq.heappop(self._queue)[-1]
# 在Python中实例化对象是不可以直接进行比较的例如
class Item:
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Item {!r}'.format(self.name)
# a = Iter('foo') b = Iter('bar'), 进行a<b比较会输出报错
# 一个优先级队列的简单调用示例
if __name__ == "__main__":
q = PriorityQueue()
q.push(Item("foo"), 1)
q.push(Item("bar"), 5)
q.push(Item("spam"), 4)
q.push(Item("grok"), 1)
a = q.pop()
b = q.pop()
c = q.pop()
d = q.pop()
print(a)

View File

@@ -0,0 +1,38 @@
from collections import defaultdict
# 当你新建一个普通字典对字典中不存在的key进行调用时会报错
a = {}
try:
print(a["key"])
pass
except:
print("err")
# 如果使用defaultdict进行字典初始化建立就不存在这个问题
# 当出现不存在的key的时候会根据默认设置进行默认值创建
b = defaultdict(list)
print(b["key"])
# 但是这样就有一个问题这个key就会一直在这里等待调用如果没有用到就是垃圾
print(b)
# 这个方法可以用于记录的添加;比如一个方法如下:
pairs = [{"a":10},{"b":10},{"b":10}]
d = {}
for key, value in pairs:
if key not in d:
d[key] = []
d[key].append(value)
# 很明显这样就显得很蠢,我还要判断一下键在不在里面
# 使用defaultdict就没有这个困扰直接省略一键添加
d = defaultdict(list)
for key, value in pairs:
d["key"].append(value)
# 当然为了避免生成空键,使用这东西的时候切记在里面翻东西的时候别直接用dict[key]输入;
# 先用keys函数拿到所有键再动手

View File

@@ -0,0 +1,20 @@
from collections import OrderedDict
# 如果需要严格控制字典元素的顺序,可以使用OrderedDict
# 比如用于网络通信协议的未序列化字典对象
d = OrderedDict()
d['foo'] = 1
d['bar'] = 2
d['spam'] = 3
d['grok'] = 4
for key in d:
print(d[key])
# 这样就可以序列化得到一个有序的json编码
import json
a = json.dumps(d)
print(a)
# 尤其注意:这东西内部有一个双向链表导致它的内存开支有点恐怖,大规模情况下谨慎使用

View File

@@ -0,0 +1,28 @@
price = {
"ACME": 45.23,
"AAPL": 612.78,
"IBM": 205.55,
"HPQ": 37.2,
"FB": 10.75
}
# 对这样的数据,有时候我们想找到最大值对应的键
# 传统方法长这样
a = max(price.values())
print(a)
for key, value in price.items():
if value == a:
print(key)
# 显然,我们要对字典里的这些东西进行遍历才能根据值把键找出来
# 如果我们不想要这样的开销,可以把键值反转:
max_price = max(zip(price.values(), price.keys()))
print(max_price)
# 注意,在对键值反转的zip中使用max和min这类函数时需要注意,如果出现:
# a = {10, "AA"}, b = {10, "ZZ"}的情况
# 由于值相同,会根据键大小返回结果
# 所以如果有多个值相同的字段,还得是老办法
max_price = [key for value, key in zip(price.values(), price.keys()) if value == a]
print(max_price)

View File

@@ -0,0 +1,33 @@
# 我们有两个字典如下:
a = {
"x":1,
"y":2,
"z":3
}
b = {
"w":10,
"x":11,
"y":12
}
# 如果想要得到相同处,只需要用keys和items这类可迭代方法执行集合操作就行
# 大家都有
print(a.keys() & b.keys())
# a有b没有
print(a.keys() - b.keys())
# b有a没有
print(b.keys() - a.keys())
# 想快速给a减键,可以这样:
c = {key:a[key] for key in a.keys() - {"w", "z"}}
print(c)
# python3.9更新了使用|的字典合并和与+=一样的合并运算符|=
d = a
d |= b
print(d)