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,24 @@
from scipy.stats import trim1
if __name__ == "__main__":
items = [1, 2, 3]
items = iter(items)
# 如果需要访问可迭代对象中的元素可以使用next函数
while True:
item = next(items, None)
if item is not None:
print(item)
else:
break
# next函数的第一个参数是一个可迭代对象第二个参数是None是没有元素的时候的返回值
# 如果不限制迭代器在没有元素后的返回值迭代器在迭代结束后会抛出一个StopIteration的错误
while True:
try:
item = next(items)
except StopIteration:
print("没东西了")
break

View File

@@ -0,0 +1,13 @@
if __name__ == "__main__":
my_list = [1,2,3,4,5,6,7,8,9]
# 有时候,我们想要在迭代的时候知道元素的下标,有些傻子(比如我)就很傻逼的做了个计数器
# 但是其实直接使用enumerate就行
for index, number in enumerate(my_list, start=0):
print(index, number)
# 但是如果可迭代对象的子元素是元组,那请务必别把元组的标识拆开
my_list = [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
for index, (x, y) in enumerate(my_list, start=1):
print(index, x, y)

View File

@@ -0,0 +1,30 @@
if __name__ == '__main__':
# 如果想要同时迭代多个序列那么可以使用zip函数
list1 = [1, 2, 3, 4, 5]
list2 = ['a', 'b', 'c', 'd', 'e']
for i, j in zip(list1, list2):
print(i, j)
# zip遵循最短木板原则迭代长度等于最短的可迭代对象长度如果想要打破这种限制请使用itertools.zip_longest()
from itertools import zip_longest
short_list = [1, 2, 3]
# fillvalue字段用来填充短列表的缺失值默认为None
for i, j in zip_longest(short_list, list1, fillvalue=0):
print(i, j)
# zip函数会构建一个元组它的长度与输入的可迭代对象数量有关
for i in zip(short_list, list2, list1):
print(i)
# 双对象元组可以直接视作键值对转成字典
dic = dict(zip(list1, list2))
print(dic)
# 重点zip函数返回的是一个一次性迭代器如果需要长久保存请转成列表在内存里持久化
storage_list = list(zip(list1, list2))

View File

@@ -0,0 +1,12 @@
from itertools import chain
if __name__ == '__main__':
a = [1,2,3,4,5]
b = ['a','b','c','d','e']
# 正常来说我们想要迭代这两个东西需要写两个循环构建两个迭代器但这样很操蛋不如直接用chain把他俩作链表连起来
for i in chain(a, b):
print(i)
# 使用chain可以避开 a + b 要求a和b类型相同的限制同时这种操作更加快速因为其底层是用指针完成而不会创建一个新的东西

View File

@@ -0,0 +1,41 @@
import os
from fnmatch import fnmatchcase
if __name__ == "__main__":
base_path = "D:\Code\Learn\practice"
# 想要建立一个处理管道需要将几个生成器函数堆叠比如我现在要输出所有practice文件夹下的注释行内容
# 1.首先生成文件夹路径
def gen_dir_path(fpath):
for path, dir, files in os.walk(fpath):
for file in files:
if (not fnmatchcase(path, "*.[git][idea]*")) and (not fnmatchcase(file, "*.md")):
yield os.path.join(path, file)
# 2.打开文件
def gen_file(paths):
for path in paths:
f = open(path, 'rt', encoding='utf-8')
yield f
f.close()
# 3.读取文件内容
def gen_file_txt(opened_files):
for file in opened_files:
yield from file
print("done")
# 4.匹配符合条件的文件行
def read_file_lines(file_lines):
for line in file_lines:
if "#" in line:
print(line)
# 将这些函数堆在一起就组成了一条管道,每次生成一个对象进行流水线处理,
# 这样避免了for循环的嵌套
paths = gen_dir_path(base_path)
files = gen_file(paths)
lines = gen_file_txt(files)
read_file_lines(lines)

View File

@@ -0,0 +1,18 @@
from collections import Iterable
if __name__ == '__main__':
# 将复杂的序列扁平化,使用递归来脱壳
def flatten(items, ignore=(str, bytes)):
for item in items:
# 要进行递归,首先这个元素要是可迭代的,其次它不能是字符串或二进制串
if isinstance(item, Iterable) and not isinstance(item, ignore):
# yield from 将请求转发到flatten函数返回的迭代器进行嵌套避免再写for循环
# yield from 在后面的协程和基于生成器的并发程序里有重要作用
yield from flatten(item, ignore)
else:
yield item
a = [1, 2, [3, 4, [5, 6], 7], 8]
for item in flatten(a):
print(item)

View File

@@ -0,0 +1,17 @@
import heapq
from itertools import chain
if __name__ == '__main__':
a = [1, 4, 7, 10]
b = [2, 5, 6, 11]
# 首先复习一下前面的知识如果不考虑合并后也是有序的用chain
for item in chain(a, b):
print(item)
# 但如果我们想要得到有序合并序列那就要用堆自带的merge功能了利用小根堆的特殊性来排序
new_arr = heapq.merge(a, b)
for item in new_arr:
print(item)
# 记住heapq的merge事先不会对输入可迭代对象的有序性进行检查而是每次从可迭代对象序列里取出最小的第一个进堆

View File

@@ -0,0 +1 @@
Hello PythonCookBook

View File

@@ -0,0 +1,33 @@
if __name__ == "__main__":
CHUNKSIZE = 10
def render(s):
# 军火展示
print(s.read())
s.seek(0)
# 在处理文件的时候我们习惯用while循环来迭代数据
print("一般while处理")
while True:
data = s.read(CHUNKSIZE)
if data == b'':
break
print(data)
s.seek(0)
# 但是可以使用迭代器来升级一下
print("进化成迭代器:")
for chunk in iter(lambda: s.read(CHUNKSIZE), b''):
print(chunk)
path = "4.迭代器与生成器/16.test.txt"
# 二进制打开文件记得用rb下一章进化一下文件读取方面的知识
f = open(path, 'rb')
render(f)
print("Done")

View File

@@ -0,0 +1,28 @@
if __name__ == "__main__":
class Node:
def __init__(self, value):
self._value = value
self._children = []
def __repr__(self):
return 'Node({!r})'.format(self._value)
def add_child(self, node):
self._children.append(node)
# 对象的内置iter方法在迭代对象的时候将迭代请求转发返回children的迭代器对象
# iter函数和len函数一样底层原理都是返回对象的底层方法iter返回对象的__iter__()
def __iter__(self):
return iter(self._children)
root = Node(0)
child1 = Node(1)
child2 = Node(2)
root.add_child(child1)
root.add_child(child2)
for ch in root:
print(ch)

View File

@@ -0,0 +1,52 @@
if __name__ == '__main__':
def fbb(start, stop, step):
x = start
while x <= stop:
yield x
x += step
# 上面是一个生成器函数,它只会在相应迭代时运行
# 在调用生成器函数的时候,因为直接生成了数字,所以有返回值
for i in fbb(0, 10, 1):
print(i)
# 尝试使用fbb生成金字塔
# 先用生成器整一个斐波那契数列生成函数
def fbb_arr(n):
index = 0
a0 = 1
a1 = 1
while index < n:
yield a0
a0, a1 = a1, a0 + a1
index += 1
# 按照n行打印出来
def print_num_delta(n):
# 计算需要生成多少个数字
fbb_number_num = sum(range(1, n + 1))
# 生成数字并保存
fbb_list = list(fbb_arr(fbb_number_num))
# 数字下标,用于遍历中保存位置
start_index = 0
# 每一行的数字数量
for number_num in range(1, n + 1):
# 切片用空格分隔后转成字符串
nums = ' '.join(str(item) for item in fbb_list[start_index: start_index + number_num])
# 格式化打印
print(format(nums, r' ^{}'.format(len(str(fbb_list[-1])) * n)))
# 更新下一行的数字下标
start_index = start_index + number_num
print_num_delta(5)
# 生成器里为什么没有return: 如果一个函数里包含yield语句那就会被识别为生成器函数
# 函数里的return此时自动失效被替换成生成器
# 生成器函数在识别到return时意识到生成结束返回的StopIteration交给for识别

View File

@@ -0,0 +1,31 @@
# 这是标准的
class Node:
def __init__(self, value):
self.value = value
self._children = []
def __repr__(self):
return "Node({})".format(self.value)
def add_child(self, node):
self._children.append(node)
def __iter__(self):
return iter(self._children)
def depth_first(self):
yield self
for child in self:
yield from child.depth_first()
if __name__ == '__main__':
root = Node(0)
child1 = Node(1)
child2 = Node(2)
root.add_child(child1)
root.add_child(child2)
child1.add_child(Node(3))
child2.add_child(Node(4))
for ch in root.depth_first():
print(ch)

View File

@@ -0,0 +1,31 @@
if __name__ == "__main__":
a = [1, 2, 3, 4]
# python自带的reversed函数搞定了反向迭代其本质时调用了__reversed__方法
for i in reversed(a):
print(i)
for i in a.__reversed__():
print(i)
# 如果想要实现类的反向迭代可以在实现__iter__()方法的同时搞一个__reversed__()方法
class Countdown:
def __init__(self, start):
self.start = start
def __iter__(self):
n = self.start
while n > 1:
yield n
n -= 1
def __reversed__(self):
n = 1
while n <= self.start:
yield n
n += 1
a = Countdown(10)
for i in reversed(a):
print(i)

View File

@@ -0,0 +1,38 @@
from collections import deque
if __name__ == "__main__":
# 在学到了生成器函数以后,有一个巨大陷阱那就是尝试用生成器函数解决一切问题
# 当生成器函数需要与外界交互的时候,就会让它非常复杂
# 所以生成器我们就让它安心生成,在需要记录或者与外界交互的时候,写一个生成器类
class FbbIterClass:
def __init__(self,nums, history_len=3):
self.nums = nums
self.history = deque(maxlen=history_len)
def __iter__(self):
a0, a1 = 1, 1
index = 0
while index < self.nums:
self.history.append(a0)
yield a0
a0, a1 = a1, a0 + a1
index += 1
fbbs = FbbIterClass(5)
# 先用生成器生成,结果在生成的过程中会存入历史队列
for i in fbbs:
print(i)
# 当然在使用for之外的方法进行迭代时需要额外套一层iter来转发请求到__iter__()
fbb_iter = iter(fbbs)
print(fbb_iter.__next__())
print(fbb_iter.__next__())
print(fbb_iter.__next__())
print(fbb_iter.__next__())
print(fbb_iter.__next__())
# 这种方法的好处是,可以在迭代时随时暴露一些东西给外部程序,比如属性和状态
for line in fbbs.history:
print("history{}".format(line))

View File

@@ -0,0 +1,26 @@
from itertools import islice
if __name__ == '__main__':
# 在程序生成过程中,我们有时候需要做一些无限生成器,这些生成器往往需要切片使用
def infinity_iterator(start):
while True:
yield start
start += 1
# 无限生成器
for i in infinity_iterator(0):
print(i)
break
# 想要对无限生成器进行切片我们就需要使用itertools里的islice函数,记得这个函数也是左闭右开
iterator= infinity_iterator(0)
iter_10_20 = islice(infinity_iterator(0), 10, 21)
for i in iter_10_20:
print(i)
# 注意islice操作是通过丢弃索引序列前的元素实现的返回的是一个一次性迭代器被迭代过后元素就被消耗掉无了
print("再次使用迭代")
for i in iter_10_20:
print(i)

View File

@@ -0,0 +1,22 @@
from itertools import dropwhile, islice
if __name__ == '__main__':
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"]
# 想要对可迭代对象进行过滤也可以使用dropwhile函数,比如这里我想过滤掉前几行有#的东西
for i in dropwhile(lambda x : x.startswith('#'), words):
print(i)
# dropwhile会在迭代时对函数进行匹配将符合条件的值丢弃直到出现第一个符合条件的值后停止工作返回所有剩余内容
# 如果你知道需要跳过几个元素那可以直接用islice进行切片操作来过滤
items = ['a', 'b', 'c', 1, 2, 3]
# None表示[3:]
for i in islice(items, 3, None):
print(i)
# 当然,使用列表的过滤方法也可以删除一些不要的东西,但是这样的删除是全局的,而不是仅在开头生效

View File

@@ -0,0 +1,23 @@
from itertools import permutations, combinations
if __name__ == '__main__':
# 有时候我们想对可迭代对象中的元素进行排列组合这个时候我们就不得不靠for循环写出很不python的代码
# itertools库帮助我们解决了这个困扰
items= ['a', 'b', 'c', 'd', 'e']
# permutations会列出所有的排列如果指定排列长度那就会输出该长度下所有的排列
for p in permutations(items):
print(p)
for p in permutations(items, 3):
print(p)
# 如果想要得到特定长度的组合那就可以使用combination函数
for c in combinations(items, 3):
print(c)
# 上面这种组合是不放回的组合如果想产生放回元素的组合可以使用combinations_with_replacement函数
from itertools import combinations_with_replacement as cwr
for c in cwr(items, 3):
print(c)