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,16 @@
# 要编写一个接受任意数量参数的函数,可以使用*
def avg(first, *rest):
return (first + sum(rest))/(len(rest) + 1)
# 如果是关键字类型的参数,那就需要使用**
def make_element(name, value, **attrs):
for item in attrs.items():
print("'{} = {}'".format(*item))
return 0
# *与**有使用上的限制,它们必须在所有参数的最后,**必须在*后面
def anyargs(*args, **kwargs):
print(args)
print(kwargs)

View File

@@ -0,0 +1,24 @@
# 这里我们要介绍一下协程的机制,协程是在单个线程内让两个函数交替执行的一种形式
# 以著名问题生产者和消费者作为基底进行讨论
def consumer():
return_str = ''
while True:
print(1)
n = yield return_str
if not n:
return
print("消费者正在消费{}".format(n))
return_str = "200 OK"
def producer(c):
next(c)
n = 0
while n < 5:
n = n + 1
print("生产者正在生产{}".format(n))
return_str = c.send(n)
print("消费者收到消息返回{}".format(return_str))
c.close()
con = consumer()
producer(con)

View File

@@ -0,0 +1,43 @@
def apply_async(func, args, *, callback):
result = func(*args)
callback(result)
def print_result(result):
print(result)
def add(x, y):
return x + y
# 如果只是简单的调用回调函数,那直接用就可以了
apply_async(add, (1, 2), callback=print_result)
apply_async(add, ('hello', 'world'), callback=print_result)
# 但是,如果我想要知道这个函数被调用了几次,携带这些保存的信息返回,可以这样改写:
def make_handler():
sequence = 0
def handler(result):
nonlocal sequence
sequence += 1
print('[{}] Got: {}'.format(sequence, result))
return handler
handler = make_handler()
apply_async(add, (1, 2), callback=handler)
apply_async(add, (1, 2), callback=handler)
# 当然我们也能用协程去搞定它:
# 协程的复习在10.1中,单步调试你就看懂了
def make_handler_v2():
sequence = 0
while True:
result = yield
sequence += 1
print('[{}] Got: {}'.format(sequence, result))
handler = make_handler_v2()
next(handler)
apply_async(add, (1, 2), callback=handler.send)
apply_async(add, (1, 2), callback=handler.send)
apply_async(add, (1, 2), callback=handler.send)

View File

@@ -0,0 +1,48 @@
# 如果我们像上一节一样写一堆小函数在代码里,相信我你很快就会暴毙
# 我们希望我们的内敛回调看起来比较正常
# 我们有这样一个函数来调用回调:
def apply_async(func, args, *, callback):
result = func(*args)
callback(result)
from queue import Queue
from functools import wraps
class Async:
def __init__(self, func, args):
self.func = func
self.args = args
def inline_async(func):
@wraps(func)
def wrapper(*args):
f = func(*args)
result_queue = Queue()
result_queue.put(None)
while True:
result = result_queue.get()
try:
a = f.send(result)
apply_async(a.func, a.args, callback=f.send)
except StopIteration:
break
return wrapper
def add(x, y):
return x + y
@inline_async
def test():
r = yield Async(add, (2, 3))
print(r)
r = yield Async(add, ('hello', 'world'))
print(r)
for n in range(5):
r = yield Async(add, (n, n))
print(r)
print("Bye")
# 这个东西比较高级,一般不使用这种方法,会让代码可读性变差
# 拒绝个人炫技,回归可读本质,从你我做起
test()

View File

@@ -0,0 +1,69 @@
# 我们有时候可以用函数来拓展闭包,使闭包获得类似类的效果
def sample():
n = 0
def func():
print("n=", n)
def get_n():
return n
def set_n(value):
# nonlocal让我们可以访问闭包内的变量有点类似类里的self
nonlocal n
n = value
# 我们能这么做的本质原因还是因为Python里的万物皆类特性
func.get_n = get_n
func.set_n = set_n
return func
f = sample()
f()
# 可以看到这里并没有出现代码提示,因为基类没有包含这些东西,它们是在动态编译的时候加入的
f.set_n(10)
f()
f.get_n()
import sys
# 比如下面有个类
class ClosureInstance:
def __init__(self, locals=None):
if locals is None:
locals = sys._getframe(1).f_locals
self.__dict__.update((key, value) for key, value in locals.items() if callable(value))
def __len__(self):
return self.__dict__['__len__']()
# 这是用这个类实现的栈实例
def Stack():
items = []
def push(item):
items.append(item)
def pop():
items.pop()
def __len__():
return len(items)
return ClosureInstance()
# 这是正常的写法
class Stack2:
def __init__(self):
self.items = []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def __len__(self):
return len(self.items)
# 从执行来说闭包的写法比正常写法块8%因为不需要访问额外的self变量
# 不!要!这!么!做!除非有非得这样干的理由,否则别这样搞,老老实实写类,这样的闭包只有类的功能而没有继承多态这些类属性

View File

@@ -0,0 +1,13 @@
# 在*参数和**参数之间可以加入普通参数这种普通参数被称为keyword_only参数
def recv(maxsize, *, block):
print("recv msg")
pass
# 这类参数只能被指定输入,示例如下:
recv(1024, True) # 报错TypeError
recv(1024, block=True) # 正确

View File

@@ -0,0 +1,5 @@
# 有时候我们会想要将函数参数加上类型提示来方便其他人快速熟悉函数,那么可以这样做:
def test_function(x:int, y:int)->int:
x = x**2
return x+y

View File

@@ -0,0 +1,6 @@
# 如果需要从函数中返回多个值,只需要返回一个元组即可
def fun():
return 1, 2, 3
a, b, c = fun()

View File

@@ -0,0 +1,37 @@
# 定义函数时,如果想要传入可选的参数,可以给参数加上默认值
def span(a, b=42):
print(a, b)
span(1)
span(1, 2)
# 如果给参数指定默认值为None那么该参数就可以传入可变容器
def span_v2(a, b=None):
print(a, b)
span_v2(1, [1, 2])
# 但是如果你不想设置一个默认值如果b没有传入参数那就提示那么你需要给一个obj
_no_value = object()
def span_v3(a, b=_no_value):
if b is _no_value:
print("no b")
span_v3(1)
# 注意,函数的默认参数只会在函数首次被调用的时候绑定一次,函数第一次被调用后默认参数就不可变了
x = 3
def su_ka(a = x):
print(a)
su_ka(1)
x = 4
su_ka()
# 不要用【】这种地址型数据做默认参数,因为它真的可以在过程中被修改
x = []
def su_ka(a = x):
print(a)
su_ka()
x.append(1)
su_ka()
# 上面使用object作为空参数传入也有这方面的考量因为用户的输入是不可预知的而obj几乎不可能被用户创建

View File

@@ -0,0 +1,8 @@
# 如果我们需要一个短小精悍的函数那么lambda函数是唯一的选择
add = lambda x, y: x + y
print(add(2,3))
# 就比如在sort函数里
names = ["David Beazley", "Brain Jones", "Raymond Hettinger", "Ned Batchelder"]
print(sorted(names, key=lambda name: name.split()[-1].lower()))

View File

@@ -0,0 +1,30 @@
if __name__ == "__main__":
# lambda函数中的变量如果被赋值了是可以动态修改的只要在每次调用之前修改就能实现变化
x = 1
a = lambda y: x + y
print(a(10))
x = x + 9
print(a(10))
x = x + 10
print(a(10))
# 如果你希望和正常函数一样在定义的时候绑死变量的值,那么你需要这样做
b = lambda y, t=x: t + y
print(b(10))
x = x-1
print(b(10))
# 比如有个比较聪明的函数
func = [lambda x : x + n for n in range(5)]
for f in func:
print(f(0))
func2 = [lambda x, n=n: x + n for n in range(5)]
for f in func2:
print(f(0))

View File

@@ -0,0 +1,31 @@
import math
from functools import partial
# 假设我们有这样一个函数
def spam(a, b, c, d):
print(a, b, c, d)
if __name__ == '__main__':
# 这个函数的输入参数有一大堆,但是其中几个是固定的,那就有用了
s1 = partial(spam, 1) #固定a=1
s2 = partial(spam, d=2) # 固定d=2
s3 = partial(spam, 3, 3, d=3) # 固定a=3 b=3 d=3
s1(2,3,4)
s2(1,2,3)
s3(1)
# partial返回的是一个被填充了部分参数的函数,参数数量等于被包装的函数的剩余参数个数
# 这个函数可以用来适配一些参数数量受限的复用场景, 比如sorted函数的key参数仅支持单参数函数
points = [(1, 2), (3, 4), (5, 6), (7, 8)]
def dis (p1, p2):
x1, y1 = p1
x2, y2 = p2
return math.hypot(x2-x1, y2-y1)
pt = (4, 3)
s = partial(dis, pt)
print(sorted(points, key=s))

View File

@@ -0,0 +1,16 @@
from urllib.request import urlopen
class UrlTemplate:
def __init__(self, template):
self.template = template
def open(self, **kwargs):
return urlopen(self.template.format_map(kwargs))
# 对于这个类,我们可以使用闭包来进行重写
def url_template(template):
def opener(**kwargs):
return urlopen(template.format_map(kwargs))
return opener