流畅的Python(七)-函数装饰器和闭包

news2024/12/28 5:23:52

一、核心要义

主要解释函数装饰器的工作原理,包括最简单的注册装饰器和较复杂的参数化装饰器。同时,因为装饰器的实现依赖于闭包,因此会首先介绍闭包存在的原因和工作原理。

二、代码示例

1、变量作用域规则

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/2/3 11:26
# @Author  : Maple
# @File    : 01-变量作用域规则.py
# @Software: PyCharm

b = 10
def f1(a):
    print(a)
    print(b)
    # b = 20 # 在函数体中给b赋值,因此会被判断为局部变量

def f1_revise(a):
    global b # 声明函数体中的b为全局变量
    print(a)
    print(b)
    b = 20

"""列表的作用域"""
students = []

def f2():
    # students指向全局变量
    students.append('a')
    return id(students)

def f3():
    # 内部再声明一个 students,其为局部变量,与外部的students不是同一个对象
    students = []
    students.append('a')
    return id(students)

def f4():
    # 声明全局变量
    global students
    students +=[1]
    # print(id(students))
    return id(students)


if __name__ == '__main__':
    # 1. f1测试
    # 说明: 1.Python在编译函数f1的定义体时,判断b为局部变量,因为在函数体中给b赋值了
    #       2.所以在调用函数f1(10)的时候,执行到print(b),发现局部变量b还没有赋值,此时就会报错
    #f1(10) # UnboundLocalError: local variable 'b' referenced before assignment

    # 2. f1_revise测试
    f1_revise(20) # 20,10
    # 全局变量b的值被修改
    print(b) # 20

    # 3.f2测试
    print(f2() == (id(students))) #True

    # 4.f3测试
    print(f3() == (id(students))) #False

    # 5.f4测试
    print(f4() == (id(students))) #True

2、闭包

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/2/3 11:35
# @Author  : Maple
# @File    : 02-闭包.py
# @Software: PyCharm

"""需求:计算移动平局值
       每调用一次函数,传入一个新的数值,然后和前面的所有值进行累加,再计算最后的平均值
"""

# 1. 借用数组方式实现
def make_avg():
    num_list = []
    def avg(new_value):
        num_list.append(new_value)
        total = sum(num_list)
        return total / len(num_list)
    return avg

# 2.直接使用变量方式实现:但存在一个坑
def make_avg_revise1():
    count =  0
    total = 0
    def avg(new_value):
        count += 1
        total += new_value
        return  total / count
    return avg

# 3.直接使用变量方式实现:填坑
def make_avg_revise2():
    count =  0
    total = 0
    def avg(new_value):
        nonlocal count,total # 通过nonlocal 将变量标记为`自由变量`
        count += 1
        total += new_value
        return total / count
    return avg


if __name__ == '__main__':

    print("***1. make_avg 测试**********************")
    # 1. make_avg 测试
    avg = make_avg()
    # 分析:1.按理说调用完 make_avg_revise1()返回avg1后,make_avg_revise1函数中的局部变量num_list的作用域应该消失了
    #       2.但实际上,在avg1中仍然能够调用num_list,这就是所谓闭包现象(变量的作用域外延了)
    #       3.num_list被称作`自由变量`
    print(avg(5))  # 5.0
    print(avg(10))  # 7.5
    # 查看avg1 创建和绑定的变量
    ## 1-1 创建的局部变量
    print(avg.__code__.co_varnames)  # ('new_value', 'total')
    ## 1-2 绑定的自由变量
    print(avg.__code__.co_freevars)  # ('num_list',)
    ## 自由变量num_list绑定在avg1的closure属性中:是一个cell对象
    print(avg.__closure__)  # (<cell at 0x000001C6095CA760: list object at 0x000001C6095C0900>,)
    ## num_list的值则在cell对象中的cell_contents属性中
    print(avg.__closure__[0].cell_contents)  # [5, 10]

    print("*** 2.调用make_avg_revise1会报错**********************")
    # 2.调用make_avg_revise1会报错
    # 分析:1. 内层函数avg的变量count 和 total在函数内部赋值,因为在函数体编译的时候,会被当作局部变量,但是又没有初始化声明,所以
    #           当函数函数调用的时候,会报错
    try:
        avg = make_avg_revise1()
        print(avg(5))
    except Exception as e:
        print(e)  #local variable 'count' referenced before assignment

    print("***  3.make_avg_revise2测试**********************")
    # 3.make_avg_revise2测试
    avg2 = make_avg_revise2()
    print(avg2(5)) # 5.0
    print(avg2(10)) # 7.5

3、装饰器

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/2/3 16:04
# @Author  : Maple
# @File    : 03-装饰器.py
# @Software: PyCharm


def decoration(fun):
    def inner(*args):
        print("do something before decorated function being excuted")
        result = fun(*args)
        print("do something after decorated function being excuted")
        return  result
    return inner

@decoration
def add(a,b):
    return  a + b

if __name__ == '__main__':

    f = add
    # f已经变成 inner,之后调用inner本质上是在调用inner函数
    print(f) # <function decoration.<locals>.inner at 0x0000015424D75310>

    # f调用过程与闭包有什么关系?
    # f = add 等价于 f = decoration(add),此后再调用f, 外层函数参数add的作用域应该已经"消失"
    # 但由于闭包原理,add作为`自由变量`,仍然会被绑定在f中
    result = f(1,2)
    """
    do something before decorated function being excuted
    do something after decorated function being excuted
    """
    print(result) # 3

4、装饰器应用

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/2/3 16:18
# @Author  : Maple
# @File    : 04-装饰器应用.py
# @Software: PyCharm

"""利用装饰器对上一章中最优策略 部分进行改写"""


from collections import namedtuple

# 顾客具名元组
Customer = namedtuple('Customer','name fidelity')

# 定义商品类
class Item:

    def __init__(self,product,quantity,price):
        """
        :param product: 商品名称
        :param quantity: 商品数量
        :param price: 商品单价
        """
        self.product = product
        self.quantity = quantity
        self.price = price


    def totol(self):
        """
        :return:订单总费用
        """
        return self.quantity * self.price


# 定义上下文(订单类)
class Order:

    def __init__(self,customer,cart,promotion=None):
        """
        :param customer: 顾客
        :param cart: 购物车
        :param promotion: 优惠策略
        """
        self.customer = customer
        self.cart = cart
        self.promotion = promotion

    def total(self):
        """
        :return:顾客订单打折之前的总费用
        """
        if not hasattr(self,'__total'):
            self.__total = sum(item.totol() for item in self.cart)
        return self.__total

    def due(self):
        """
        :return:顾客最终支付的费用
        """
        if self.promotion is None:
            return self.total()
        return self.total() - self.promotion(self)

    def __repr__(self):
        fmt = '<Order total: {:.2f} due: {:.2f}>'
        return fmt.format(self.total(), self.due())

# 策略数组
promos = []

def promotion(func):
    # 这里的promos指向全局变量,为何不是局部变量?list是可变类型,append操作并不会生成新的对象,
    promos.append(func)
    return func



# 具体策略1:积分优惠策略
# 被promotion装饰的函数,会被append到策略数组promos中
@promotion
def FidelityPromo(order):
    """如果积分大于1000,享受15%优惠"""
    if order.customer.fidelity > 1000:
        return order.total() * 0.15
    else:
        return 0

# 具体策略2
@promotion
def BulkItemPromo(order):
    """单个商品为20个及以上时,提供10%折扣"""
    discount = 0
    for item in order.cart:
        if item.quantity >= 10:
            discount += item.totol()* 0.1
    return discount

# 具体策略3
@promotion
def LargetOrderPromo(order):
    """购物车中不同商品种类数量达到3个或以上提供7%折扣"""
    discount = 0
    # 获取购物车中所有不同的商品
    products = {item.product for item in order.cart}
    if len(products) >=3:
        discount += order.total() * 0.07
    return round(discount,2)

# 最优策略
def optimization_strategy(order):
    """
    :param order: 订单类
    :return:最优策略和最大折扣
    """
    # 手动定义所有优惠策略
    p_final =  None
    discount_final = 0
    for p in promos:
        discount = p(order)
        if discount > discount_final:
            discount_final = discount
            p_final = p
    return (p_final,discount_final)


if __name__ == '__main__':
    # 1. 最优策略示例1
    cus1 = Customer('Maple', 2000)  # 用户积分大于1000,享受15%(注意:为了测试,数值从5%调整到15%)优惠
    cart1 = [Item('banana', 20, 2.0), Item('apple', 10, 1.0)]
    o1 = Order(cus1, cart1, FidelityPromo)
    print(optimization_strategy(o1))  # (<function FidelityPromo at 0x0000021CAD565310>, 7.5)


    print('=====================================================')

    # 2. 最优策略示例2
    cus2 = Customer('Jack', 880)
    cart2 = [Item('Book', 30, 1.0), Item('Radio', 5, 1.0)]  # Book订单超过20个,提供10%折扣
    o2 = Order(cus2, cart2, BulkItemPromo)
    print(optimization_strategy(o2))  # (<function BulkItemPromo at 0x0000021CAD5653A0>, 3.0)
    print('=====================================================')

    # 3. 最优策略示例3
    cus3 = Customer('Mick', 300)
    cart3 = [Item('Phone', 5, 2.0), Item('Water', 5, 1.0), Item('ring', 8, 2)]  # 购物车不同商品达到3个.提供7%折扣
    o3 = Order(cus3, cart3, LargetOrderPromo)
    print(optimization_strategy(o3))  # (<function LargetOrderPromo at 0x0000021CAD565430>, 2.17)

5、clock_deco

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/2/2 20:20
# @Author  : Maple
# @File    : 05-clock_deco.py
# @Software: PyCharm

import time
from functools import reduce
from operator import mul


def clock(func):
    """clock装饰器"""
    def clocked(*args):
        start = time.perf_counter()
        result = func(*args)
        end = time.perf_counter()
        time_takes =  end = start
        arg_str = ','.join([repr(arg) for arg in args])
        print('[%0.8fs] %s(%s) -> %s' % (time_takes,func.__name__,arg_str,result))
        return result

    return clocked

@clock
def f1(n):
    return reduce(mul,range(1,n+1))

if __name__ == '__main__':

    # clock装饰器测试
    print(f1(5))
    """[0.02694280s] f1(5) -> 120
       120
    """

6、使用functools.lur_cache做缓存

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/2/2 20:56
# @Author  : Maple
# @File    : 06-使用functools.lur_cache做备忘.py
# @Software: PyCharm


from clock_deco import clock
import functools

# 如果不使用lur_cache
# @clock
# def fibonacci(n):
#     if n < 2:
#         return n
#     return fibonacci(n-2) + fibonacci(n-1)


# 使用lru_cache
@functools.lru_cache()
@clock
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-2) + fibonacci(n-1)




if __name__ == '__main__':

    #1.原生fibonacci测试
    """打印结果
    [0.02825890s] fibonacci(0) -> 0
    [0.02828490s] fibonacci(1) -> 1
    [0.02825830s] fibonacci(2) -> 1
    [0.02829540s] fibonacci(1) -> 1
    [0.02830080s] fibonacci(0) -> 0
    [0.02830610s] fibonacci(1) -> 1
    [0.02830040s] fibonacci(2) -> 1
    [0.02829520s] fibonacci(3) -> 2
    [0.02825730s] fibonacci(4) -> 3
    3
    """
    # print(fibonacci(4))

    #2.使用lru_cache测试
    """打印结果
	[0.02470590s] fibonacci(0) -> 0
    [0.02472680s] fibonacci(1) -> 1
    [0.02470550s] fibonacci(2) -> 1
    [0.02473770s] fibonacci(3) -> 2
    [0.02470470s] fibonacci(4) -> 3
    
    结果说明:
    (1)n的每个值都只调用一次
    (2)这是因为fibonacci(n)的值会被缓存起来,下次用到的时候可以直接从缓存获取结果,而不用再重新计算
    """
    print(fibonacci(4))

补充说明原生fibonacci测试结果

7、单分派泛函数

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/2/3 9:56
# @Author  : Maple
# @File    : 07-单分派泛函数-1.py
# @Software: PyCharm
from collections import abc
import html
import numbers
from functools import singledispatch


def html_parse(obj):
    """生成Html,返回不同类型的Python对象
    :param obj: Python对象
    :return: html
    """
    content = html.escape(repr(obj))
    return '<pre>{}</pre>'.format(content)


@singledispatch
def html_parse_enhance(obj):
    """
    针对不同的Python对象,以自定义的方式显示
    1. str: 把内部的换行符替换为'<br>\n';不适用<pre>,而是使用<p>
    2. int: 以十进制和十六进制显示数字,示例: <pre>42 (0x2a)</pre>
    3. list:输出一个html列表,根据各个元素的类型进行格式化。示例:html_parse_enhance(['maple',42,{1,23}]),输出->
       <ul>
         <li><p>maple</p><li>
         <li><pre>42 (0x2a)</pre><li>
         <li><pre>{123}</pre><li>
       </ur>
    :param obj:Python对象
    :return:html
    """
    content = html.escape(repr(obj))
    return '<pre>{}</pre>'.format(content)

@html_parse_enhance.register(str)
def _(text):
    """对于str类型:把内部的换行符替换为'<br>\n';不适用<pre>,而是使用<p>"""
    content = html.escape(text).replace('\n','<br>\n')
    return '<p>{}</p>'.format(content)

@html_parse_enhance.register(numbers.Integral)
def _(n):
    """对于整数类型: 以十进制和十六进制显示数字,示例: <pre>42 (0x2a)</pre>"""
    return '<pre>{0} (0x{0:x})</pre>'.format(n)

@html_parse_enhance.register(tuple)
@html_parse_enhance.register(abc.MutableSequence)
def _(seq):
    """对于list类型: 输出一个html列表,根据各个元素的类型进行格式化"""
    content = '</li>\n<li>'.join([html_parse_enhance(obj) for obj in seq])
    return '<ul>\n<li>{}</li>\n</ul>'.format(content)


if __name__ == '__main__':

    # 1.集合对象测试
    r1 = html_parse({1,2,3})
    print(r1) # <pre>{1, 2, 3}</pre>
    r1_eh = html_parse_enhance({1,2,3})
    print(r1_eh) #<pre>{1, 2, 3}</pre>

    # 2.函数对象测试
    print('******2.函数对象测试*******************')
    r2 = html_parse(abs)
    print(r2) # <pre>&lt;built-in function abs&gt;</pre>
    r2_eh = html_parse_enhance(abs)
    print(r2_eh) #<pre>&lt;built-in function abs&gt;</pre>

    # 3.包含换行符\n的字符串测试
    print('******3.包含换行符\n的字符串测试*******************')
    r3 = html_parse('maple \n abc')
    print(r3) # <pre>&#x27;maple \n abc&#x27;</pre>
    r3_eh = html_parse_enhance('maple \n abc')
    """<p>maple <br>
        abc</p>
    """
    print(r3_eh)

    # 4.整数测试
    print('******4.整数测试*******************')
    r4 = html_parse(42)
    print(r4) # <pre>42</pre>
    r4_eh = html_parse_enhance(42) # <pre>42 (0x2a)</pre>
    print(r4_eh)

    # 5.列表对象测试
    print('******5.列表对象测试*******************')
    r5 = html_parse(['maple',33,{1,2,3}])
    print(r5) # <pre>[1, 2, 3]</pre>
    r5_eh = html_parse_enhance(['maple',33,{1,2,3}])
    """<ul>
       <li><p>maple</p></li>
       <li><pre>33 (0x21)</pre></li>
       <li><pre>{1, 2, 3}</pre></li>
       </ul>
    """
    print(r5_eh)

8、装饰器工厂函数

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/2/3 16:47
# @Author  : Maple
# @File    : 08-装饰器工厂函数.py
# @Software: PyCharm
import time
from functools import reduce
from operator import mul


registry = set()

# 定义一个装饰器工厂函数:注册或取消被装饰函数
def register(active=True):
    def decorate(func):
        print('running register(active = %s) ——> decorate(%s)'  %(active,func))
        if active:
            registry.add(func)
        else:
            registry.discard(func)
        return func
    return decorate


# 注意:装饰器工厂函数 并不是装饰器,必须作为函数调用,即后面要加(),即使不传参数
# 在f1上加上@register()后,模块加载的时候就会自动执行register里面的代码了
@register()
def f1(n):
    return reduce(mul,range(1,n+1))

@register(active=False)
def f2():
    pass

def f3():
    pass

if __name__ == '__main__':

    # 1. 模块加载的时候,就会执行register里面的代码
    # 因此会输出:
    """
    running register(active = True) ——> decorate(<function f1 at 0x000001D5F61C4F70>)
    running register(active = False) ——> decorate(<function f2 at 0x000001D5F61CC430>)
    """
    # 2.查看registry的值: 当前只有函数f1注册了
    print(registry) # {<function f1 at 0x00000141DCFAC0D0>}

    # 3.f3上并没有加@register,如何手动注册呢?
    register(active=True)(f3) # running register(active = True) ——> decorate(<function f3 at 0x00000287ECF45790>)

    # 再次查看registry:f3也被注册
    print(registry) # {<function f3 at 0x00000287ECF45790>, <function f1 at 0x00000287ED00C040>}

9、参数化clock装饰器

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/2/3 17:16
# @Author  : Maple
# @File    : 09-参数化clock装饰器.py
# @Software: PyCharm
import time
from functools import reduce
from operator import mul

DEFAULT_FOTMAT = '[{time_takes:0.8f}s] {name}({arg_str}) -> {result}'

def clock(fmt = DEFAULT_FOTMAT):
    def decorate(func):
        """clock装饰器"""
        def clocked(*args):
            start = time.perf_counter()
            result = func(*args)
            end = time.perf_counter()
            time_takes =  end - start
            name = func.__name__
            arg_str = ','.join([repr(arg) for arg in args])
            # *locals是获取clocked中的局部变量:name,arg_str等
            print(fmt.format(**locals()))
            return result
        return clocked
    return decorate


@clock()
def f1(n):
    return reduce(mul,range(1,n+1))

@clock('{name}({arg_str}): {result}')
def f2(n):
    return reduce(mul,range(1,n+1))


@clock('fun_name:{name};time_takes:{time_takes}')
def f3(n):
    return reduce(mul,range(1,n+1))


if __name__ == '__main__':
    # f1指向clocked函数
    f = f1
    print(f) #<function clock.<locals>.decorate.<locals>.clocked at 0x000001DD7193C4C0>

    # 1. 默认格式测试
    f1(4) # [0.00000460s] f1(4) -> 24

    #2.自定义格式1测试
    f2(4) # f2(4): 24

    #3.自定义格式3测试
    f3(4) # fun_name:f3;time_takes:8.000000000021878e-07

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1430373.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记录一次使用ant design 中 ConfigProvider来修改样式导致样式改变的问题(Tabs嵌套Tabs)

一 说明 继之前的一篇文章&#xff1a;antd5 Tabs 标签头的文本颜色和背景颜色修改 后&#xff0c;发现在被修改后的Tab中继续嵌套Tabs组件&#xff0c;这个新的Tabs组件样式跟外层Tabs样式也是一致的&#xff0c;如下图所示&#xff1a; 二 原因 在修改外层tabs样式时&…

学习Spring的第十三天

非自定义bean注解开发 设置非自定义bean : 用bean去修饰一个方法 , 最后去返回 , spring就把返回的这个对象,放到Spring容器 一 :名字 : 如果bean配置了参数 , 名字就是参数名 , 如果没有 , 就是方法名字 二 : 如果方法产生对象时 , 需要注入数据 , 在方法参数设置即可 , …

iOS 包含行间距计算富文本size

在一次开发过程中&#xff0c;发现带有行间距的富文本计算高度&#xff0c;会有不准确的情况&#xff0c;富文本内容明明很长&#xff0c;但是计算出的高度只有不到20像素&#xff0c;导致整个cell的高度计算异常。 需求上是文字固定宽度&#xff0c;最多显示3行&#xff0c;超…

【Simulink系列】——动态系统仿真 之 简单系统

引入 不同的系统具有不同的输入与输出。一般来说&#xff0c;输入输出数目越多&#xff0c;系统越复杂。最简单的系统只要一个输入一个输出&#xff08;SISO&#xff09;&#xff0c;且其任意时刻的输出只与当前时刻的输入有关。 一、简单系统定义 对于满足下列条件的系统&a…

android 网络拦截器统一处理请求参数和返回值加解密实现

前言 项目中遇到参数加密和返回结果加密的业务 这里写一下实现 一来加深记忆 二来为以后参考铺垫 需求 项目在开发中涉及到 登陆 发验证码 认证 等前期准备接口 这些接口需要单独处理 比如不加密 或者有其他的业务需求 剩下的是登陆成功以后的业务需求接口 针对入参和返回值…

【Android新版本兼容】onBackPressed()方法被弃用的解决方案

提示&#xff1a;此文章仅作为本人记录日常学习使用&#xff0c;若有存在错误或者不严谨得地方欢迎指正。 文章目录 一、使用 AndroidX API 实现预测性返回手势1.1 添加依赖1.2 启用返回手势1.3 注册OnBackPressedCallback()方法来处理返回手势 一、使用 AndroidX API 实现预测…

【MIT 6.S081】2020, 实验记录(5),Lab: lazy allocation

目录 Task 1: Eliminate allocation from sbrk()Task 2: Lazy allocationTask 3: Lazytests and Usertests 在学习了 page fault 这一节课后&#xff0c;了解了操作系统是如何结合 page table 和 trap 利用 page fault 来实现一系列的神奇的功能。这个 lab 就是在 XV6 中实现 l…

前端面试拼图-数据结构与算法

摘要&#xff1a;总结一些前端算法题&#xff0c;持续更新&#xff01; 一、数据结构与算法 时间复杂度-程序执行时需要的计算量&#xff08;CPU&#xff09; 空间复杂度-程序执行时需要的内存空间 前端开发&#xff1a;重时间&#xff0c;轻空间 1.把一个数组旋转k步 arr…

CSS的复合选择器

一,什么是复合选择器 常用的复合选择器有:后代选择器、子选择器、并集选择器和伪类选择器。 二,后代选择器(用空格)(重点) 后代选择器也称包含选择器,可以选择父元素里面的子元素。写法就是外层标签在前面,内层标签写后面,中间要有空格隔开。当标签发生嵌套时,内层…

PostgreSQL 也很强大,为何在中国大陆,MySQL 成为主流,PostgreSQL 屈居二线呢?

问题&#xff1a; PostgreSQL 也很强大&#xff0c;为何在中国大陆&#xff0c;MySQL 成为主流&#xff0c;PostgreSQL 屈居二线呢&#xff1f;PostgreSQL 能否替代 MySQL&#xff1f; 当我们讨论为何 MySQL 在中国大陆成为主流而 PostgreSQL 屈居二线时&#xff0c; 我们其实…

servlet会话API

servlet会话API 您可以使用servlet会话API中定义的类和接口来创建和管理用户会话。servlet会话API提供的用于创建和管理用户会话的各种接口有javax.servlet.http.HttpSession、javax.servlet.httpSessionListener和javax.servlet.http.HttpSessionBindingListener和javax.serv…

unity角色触摸转向

1、挂载脚本到角色的父物体A上 2 、以屏幕左边的触摸为移动&#xff0c;右边为转向操作 3、加载角色时&#xff0c;将角色的父物体设置为A&#xff0c;须将角色的位置和角度置0 using System; using System.Collections; using System.Collections.Generic; using UnityEngin…

OTG -- STM32 OTG驱动代码下载及简述(三)

目录 前沿 1 STM32 OTG标准库的获取 2 设备模式代码匹配开发板 2.1 OTG FS全速代码修改 2.2 OTG HS代码修改 2.2.1 OTG HS外部高速PHY运行在高速模式代码修改 2.2.2 OTG HS外部高速PHY运行在全速模式代码修改 2.2.3 OTG HS内部全速PHY运行在全速模式代码修改 前沿 前面…

linux 组建和卸载raid1、raid0详细操作

组raid的最好是相同容量和型号的硬盘&#xff0c;否则会有木桶效应 linux下组raid有很多细节 一、安装raid软件 deb包 apt-get install mdadm或dnf包 dnf install mdadm二、组raid1-镜像&#xff0c;组raid0-并列 raid1和raid0只有在madam命令时一点点不同&#xff0c;其他…

python 下载腾讯在线文档

import requests""" 1. 手动到chrome获取下载请求 2. 获取excel的动态id 3. 拼出excel的下载链接 4. 下载 """class Excel:def __init__(self):self.cookie_string ""self.headers {"authority": "docs.qq.com"…

中缀转后缀

概念 什么是后缀表达式&#xff1f; 后缀表达式&#xff0c;其实就是一个中缀表达式 AOB > ABO &#xff08;A、B是式子、O 为运算符&#xff09;&#xff0c;将运算符向后放 中转后举例 中缀表达式&#xff1a;&#xff08;a b&#xff09;* c - (d / c) 首先&#xff…

CANoe学习笔记—关于cfg工程界面的分类

创建一个工程过程中&#xff0c;如何规划好界面设置&#xff0c;对于后续使用和维护起到了非常好的作用。故整理下 1&#xff1a;首先规划好大致结构图 CANoe中工程的规划Trace界面ConfigurationBuildInToolControlDiagnosticPanel预留 当然&#xff1a;此格式不是固定的&…

高级FPGA开发之基础协议PCIe

基础协议之PCIe部分 一、TLP包的包头 在PCIe的系统中&#xff0c;tlp包的包头的结构有许多部分是相似的&#xff0c;通过掌握这些常规的包头&#xff0c;能帮助理解在PCIe总线上各个设备之间如何进行数据的收发。 通用的字段 通用字段作用Fmt决定了包头是3DW还是3DW&#xff…

20240203在WIN10下配置stable-diffusion-webui.git

20240203在WIN10下配置stable-diffusion-webui.git 2024/2/3 11:55 【结论&#xff1a;在WIN10下&#xff0c;生成512x512分辨率的图像&#xff0c;大概需要9秒钟&#xff01;】 【结论&#xff1a;在Ubuntu20.04.6下&#xff0c;生成512x512分辨率的图像&#xff0c;大概需要1…

Unity 图片不改变比例适配屏幕

Unity 图片不改变比例适配屏幕 前言项目场景布置代码编写添加并设置脚本效果 前言 遇到一个要让图片适应相机大小&#xff0c;填满屏幕&#xff0c;但不改变图片比例的需求&#xff0c;记录一下。 项目 场景布置 代码编写 创建AdaptiveImageBackground脚本 using System.C…