# 编程语言类

# python 相关

装饰器

@function

语法糖指编程语言中添加的简化语法结构,比如在 C 语言中, a[i] 就是 *(a+i) 的一个语法糖,而这里的 @用法也是。

装饰器本身是一种高级函数,它的参数和返回值都是一个函数
是对函数包装

from fuctools import wraps
def decoration(f): #接受被装饰的函数
	@wraps(f)  #wrap 本身也是一个装饰器,用于保留原始函数数据
	def decoration_fuction(*args,**kwargs): #实际的包装函数
    	pass
   	return decoration_fuction

在使用时:

@decoration #无需参数
def potato(potatowo:str):
    print(potatowo)

它等价于:

def potato(potatowo:str):
    print(potatowo)
potato=decoration(potato)
#从这里也可看出为什么会发生参数覆盖的问题,wraps 实际上只是将原函数的所有内容都复制给了新的函数(包括__name__之类的)这是的函数名和参数等都完整保留了下来

还有一种使用双层函数(实际上应该算三层了),此时需要参数

def repeat(n):
	def decoration(f):
        @wraps(f)
        def decroation_function(*args,**kwargs):
#原先的参数数量和类型不可预知,使用 * args 接受任意数量的普通变量。**kwargs 接受有关键字的参数,存储为字典(这跟其实际类型没有关系!!!!!!!只跟传参时的写法有关)
#这是 * 和 ** 的作用,与名称无关,并且在其之前可以有其他必须的参数
            ...
            return result
        return decoration_function

实际使用时:

@repeat(3)
def potato(potatowo:str):
	print(potatowo)

它的等价形式类似上面,但是是两层调用:

potato=repeat(3)(potato)

作用只是在给实际的装饰函数额外传递参数)

在 flask 中

@app.route("show")
def show():
	pass

实际上是:

show=app.route("show")(show) #类中的函数也可以是装饰器

那么应当知道:

1765115781040

这类装饰器

g 对象

flask 框架中所有的函数都是在不同的线程中执行的,g 对象可以实现在请求层面的共享数据,在请求处理完成前,所有的函数(视图,中间件,工具函数等)都可以读写同一个 g

from flask import Flask,g,request
app=Flask(__name__)
def get_current_username():
    user_id=request.args.get("user_id")
    user={"id":user_id,"name":f"用户{user_id}"}
    g.current_user=user #存入 g
    return user
@app.route("/user/info")
def user_info():
    get_current_user() #调用工具函数,向 g 中存入用户
    return f"当前用户{g.current_user['name']}"
#从 g 中读取

python 中的 SQLite 是不支持多个线程读写的,不能通过全局对象来实现读写 db,此时可以使用 g 来实现针对请求的数据库连接,避免频繁开启关闭

反射

在程序运行时动态的获取类信息(属性,方法,构造函数),创建对象,调用方法的技术,无需在编译期确定具体类名

反射

IOC

Inversion of Colltroll (控制反转) 用于各种对象,模块,系统等之间的解耦

通过加入第三方来实现

1765114670539

1765114691381

在正常流程中,如果对象 A 依赖于 B,那就必须在对象 A 初始化或者运行到某一点时,主动去创建对象 B 或者使用已经创建的对象 B。而在 IOC 中,我们使用容器来处理,对象 A 和对象 B 不再具有直接的联系,当对象 A 需要对象 B 的时候,IOC 容器会主动创建一个对象 B 注入到需要的地方,此时将对象 A 获得对象 B 的过程从主动变成了被动的过程,控制权有外部的容器来实现

之前在学 thinkphp 时,就有出现过容器这个概念

1765115489315

这里,我们将将一个实例存入容器中,之后直接注入到需要它的地方

// 原本:业务代码自己创建 Cache 实例(自己掌控控制权)
$customCache = new think\Cache([
    'type' => 'redis',
    'host' => '127.0.0.1'
]);
// 现在:把实例绑定到容器(控制权交给容器)→ 这是 IoC 思想的体现
bind('cache', $customCache);
// 后续用的时候:从容器获取实例(容器把依赖 “注入” 到业务代码)→ 这是 DI 的实现
$cache = app('cache');

这样我们就可以通过容器,存储我们需要的类然后在需要的地方直接将其注入。

在 python 中有 inspect 模块,用于实现反射,它的作用时获取对象信息,获取定义这个对象的模块,源文件路径,源代码之类的功能

import inspect
import math
print(inspect.getmodule(math.sin))  # 输出: <module 'math' (built-in)>
print(inspect.getdoc(math.sin))     # 输出: Return the sine of x (measured in radians).
print(inspect.getfile(math))        # 输出: /path/to/python/lib/python3.x/math.py

具体见 Python(inspect) - 做梦当财神 - 博客园

import inspect
def add(x, y=10):
    return x + y
def dynamic_call(func, *args, **kwargs):
    bound_args = inspect.signature(func).bind(*args, **kwargs)
    bound_args.apply_defaults()
    return func(*bound_args.args, **bound_args.kwargs)
print(dynamic_call(add, 5))        # 15
print(dynamic_call(add, 5, y=20))  # 25

这里实现了参数的动态绑定

其中:

def add(x,y=10) #

再次回到

1765115781040

这里的 bot,event 等参数都是通过注入实现的 (args 先解析再注入)