当前位置: 首页 > news >正文

Python函数——万字详解

 

  

                                       ——    

导 语:    

         从今天开始,我们将进入第二模块的学习——函数。第一模块主要是学习python基础知识,从第二模块开始就可以通过程序去解决工作中实际的问题。从今天开始,我们将进入第二模块的学习,此模块主要是:

  • 函数,一个用于专门实现某个功能的代码块(可重用)

1、内置函数

len、bin、oct、hex 等

2、自定义函数

def send_email():# 实现了发送邮件的代码pass
send_email()

3、模块,集成了很多功能的函数集合

  • 内置模块,Python内部帮助我们提供好的。

    import random
    num = random.randint(0,19)
    
    import decimalv1 = decimal.Decimal("0.1")
    v2 = decimal.Decimal("0.2")
    v3 = v1 + v2
    print(v3) # 0.3
    
  • 第三方模块,网上下载别人写好的模块(功能集合)。

  • 自定义模块

一. 文件操作

在学习文件操作之前,先来回顾一下编码的相关以及先关数据类型的知识。

  • 字符串类型(str),在程序中用于表示文字信息,本质上是unicode编码中的二进制。

    name = "武沛齐"
    
  • 字节类型(bytes)

可表示文字信息,本质上是utf-8/gbk等编码的二进制(对unicode进行压缩,方便文件存储和网络传输。)

name="小峰"
print(name.encode('utf-8'))
data=b'\xe5\xb0\x8f\xe5\xb3\xb0'
print(data.decode('utf-8'))#小峰

可表示原始二进制(图片、文件等信息)

#	- 路径:
#		相对路径:'info.txt'
#		绝对路径:'/Users/PycharmProjects/luffyCourse/day09/info.txt'
# 	- 模式
# 		rb,表示读取文件原始的二进制(r, 读 read;b, 二进制 binary;)
#

在这里对于文件的文件打开的模式我们就不再一一介绍了, 主要参考:

https://docs.python.org/3/library/functions.html#filemodes

模式 介绍
‘r’ 读取
‘w’   清空文件内容,然后写入
‘x’   新建文件,然后写入(如果文件存在,那直接失败)
‘a’ 在文件末尾写入,文件不存在就新建
‘b’  二进制模式
‘t’   文本模式
‘+’  更新(读和写)

Python里面默认的模式是:'rt'。只要有'+',就变成了可读可写的;可以与w,r,a等进行组合。

1. 读文件

  • 读文本文件

    file_object = open('info.txt', 'rt',encoding='utf-8')
    data=file_object.read()
    print(data)
    file_object.close()
  • 读图片等非文本内容文件。

    file_object = open('my.png', 'rb')
    data = file_object.read()
    file_object.close()
    print(data)

        注意事项:路径相关问题。注意区分相对路径与绝对路径。

        windows系统中写绝对路径容易出问题:

#注意路径相关的问题
错误写法:file_object = open("D:\python\try1\info.txt","rt")  
正确写法:file_object = open("D:\\python\\try1\\info.txt","rt")
正确写法:file_object = open(r"D:\python\try1\info.txt","rt")
  • 读文件时,文件不存在程序会报错。所以一般在项目中我们会将其和os模块结合起来使用,判断一个路径是否存在。

    file_path=r"D:\python\try1\info.txt"
    exists=os.path.exists(file_path)
    if not exists:print("文件不存在")
    else:file_object = open(file_path, "rt",encoding="utf-8")data = file_object.read()print(data)file_object.close()
    

2.写文件

  • 写文本文件

    # 路径:t1.txt
    # 模式:wb(要求写入的内容需要是字节类型)
    ​1、打开文件
    file_object = open(“info.txt”, mode=‘wb’)
    # 2.写入内容
    file_object.write( “小峰”.encode(“utf-8”) )
    # 3.文件关闭
    file_object.close()
  • 写图片非文本文件等文件

    f1 = open('a1.png',mode='rb')
    content = f1.read()
    f1.close()f2 = open('a2.png',mode='wb')
    f2.write(content)
    f2.close()
    

基础案例:

#用户注册
# w写入文件,先清空文件;再在文件中写入内容。
file_object = open("files/info.txt", mode='wt', encoding='utf-8')
while True:user = input("请输入用户名:")if user.upper() == "Q":breakpwd = input("请输入密码:")data = "{}-{}\n".format(user, pwd)file_object.write(data)
file_object.close()

补充:上下文书写格式,避免忘记关闭文件

with open('info.txt', mode='rb') as f:data = f.read()print(data)

二. 初识函数

函数,可以当做是一大堆功能代码的集合。

def 函数名():函数内编写代码...函数名()

例如:

# 定义名字叫info的函数
def info():print("第一行")print("第二行")print("第n行...")info()

一般在项目开发中有会有两种应用场景:

  • 有重复代码,用函数增加代码的重用性。

    def send_email():# 10行代码print("欢迎使用计算机监控系统")
    if CPU > 90%:send_email()
    if 硬盘使用率 > 99%:send_email()
    if 内存使用率 > 98%:send_email()
    ...
    
  • 代码太长,用函数增强代码的可读性。

    def mycard():card_color_list=["红桃","方片","梅花","方片"]card_num=["1","2","3","4","5","6","7","8","9","J","Q","K","A"]card=[f"{color}{num}"for color in card_color_list for num in card_num]card.append("大王")card.append("小王")return card
    cout=0
    for i in mycard():print(i)cout+=1
    print(cout)

        以前我们变成是按照业务逻辑从上到下逐步完成,称为:面向过程编程;现在学了函数之后,利用函数编程称为:函数式编程。

1. 函数的参数

之下面就来教大家用python发邮件,以下是我为大家提供的发邮件的一个函数。

import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
​
def send_email(email):# ### 1.邮件内容配置 #### 邮件文本msg = MIMEText("在吗", 'html', 'utf-8') # 邮件上显示的发件人msg['From'] = formataddr(["小峰", "wptawy@126.com"])# 邮件上显示的主题msg['Subject'] = "邮件主题"# ### 2.发送邮件 ### server = smtplib.SMTP_SSL("smtp.126.com")server.login("wptawy@126.com", "WIYSAILOVUKPQGHY")server.sendmail("wptawy@126.com", email, msg.as_string())server.quit()v3 = "xiaofeng@live.com"
send_email(v3)

1.1 参数

在定义函数时,如果在括号中添加变量,我们称它为函数的形式参数

#定义有三个参数的函数(a1/a2/a3一般称为形式参数-形参)
def func(a1,a2,a3):print(a1+a2+a3)# 执行函数并传入参数(执行函数传值时一般称为实际参数-实参)
func(11,22,33)# 执行函数并传入参数
func(9,2,103)
  • 位置传参

    def add(n1,n2):print(n1+n2)add(1,22)
    
  • 关键字传参:只能从右往左

    def add(n1,n2):print(n1+n2)add(n1=1,n2=22)
    

1.2 默认参数

def func(a1, a2, a3=10):print(a1 + a2 + a3)# 位置传参
func(8, 19)
func(1, 2, 99)
# 关键字传参(位置和关键混合时,关键字传参要在后面)
func(12, 9, a3=90)
func(12, a2=9, a3=90)
func(a1=12, a2=9, a3=90)

1.3 动态参数

 动态参数,定义函数时在形参位置用 *或** 可以接任意个参数。在定义函数时可以用 *和**,其实在执行函数时,也可以用。

  •  *
def func(*args):print(args) # 元组类型 (22,)   (22,33,99,) ()# 只能按照位置传参
func(22)
func(22,33)
func(22,33,99)
func()
  • **

    def func(**kwargs):print(kwargs) # 字典类型 {"n1":"小峰"}    {"n1":"小峰","age":"18","email":"xxxx"}  {}# 只能按关键字传参
    func(n1="小峰")
    func(n1="小峰",age=18)
    func(n1="小峰",age=18,email="xx@live.com")
    
  • *和**

    def fun(*args,**kwargs):print(args)print(kwargs)fun(1,2,3,4,5)
    fun(13456,456,name="xiaofeng",age=19,sex="boy")

    提示:是否还记得字符串格式化时的format功能。

    v1 = "我叫{},今年{},性别{}".format("小峰",18,"男")
    v2 = "我叫{name},今年{age},性别{gender}".format(name="小峰",age=18,gender="男")
    print(v1)
    print(v2)
    
  • 注意事项:

    # 1. ** 必须放在 * 的后面
    def func1(*args, **kwargs):print(args, kwargs)
    func1(1,2,name='John')
    # 2. 参数和动态参数混合时,动态参数只能放在最后。
    def func2(a1, a2, a3, *args, **kwargs):print(a1, a2, a3, args, kwargs)
    func2(1,2,4,6,name='John',a=2,b=3,c=4)
    # 3. 默认值参数和动态参数同时存在
    def func3(a1, a2, a3, a4=10, *args, a5=20, **kwargs):print(a1, a2, a3, a4, a5, args, kwargs)
    func3(11, 22, 33, 44, 55, 66, 77, a5=10, a10=123)
    
  • 形参固定,实参用*和**

    def func(a1,a2):print(a1,a2)
    func( 11, 22 )
    func( a1=1, a2=2 )
    func( *[11,22] )
    func( **{"a1":11,"a2":22} )
    
  • 形参用*和**,实参也用 *和**

    def func(*args, **kwargs):print(args, kwargs)
    func(11, 22)
    func(11, 22, name="小峰", age=18)
    # 小坑,([11,22,33], {"k1":1,"k2":2}), {}
    func([11, 22, 33], {"k1": 1, "k2": 2})
    # args=(11,22,33),kwargs={"k1":1,"k2":2}
    func(*[11, 22, 33], **{"k1": 1, "k2": 2})
    # 值得注意:按照这个方式将数据传递给args和kwargs时,数据是会重新拷贝一份的
    # (可理解为内部循环每个元素并设置到args和kwargs中)。
    

所以,在使用format字符串格式化时,可以可以这样:

v3 = "我是{},年龄:{}。".format(*["小峰",18])
v4 = "我是{name},年龄:{age}。".format(**{"name":"小峰","age":18})
print(v3)
print(v4)

2. 函数返回值

在开发过程中,我们希望函数可以帮助我们实现某个功能,但让函数实现某功能之后有时也需要有一些结果需要反馈给我们,例如:

def func():return 6666
print(func())
def func(a):return a+10
print(func(2))
  • 返回值可以是任意类型,如果函数中没写return,则默认返回None

    def func():value = 1 + 1ret = func()
    print(ret) # None
    

    当在函数中未写返回值 或 return 或 return None ,执行函数获取的返回值都是None。

    def func():value = 1 + 1return  # 或 return Noneret = func()
    print(ret) # None
    
  • return后面的值如果有逗号,则默认会将返回值转换成元组再返回。

    def func():return 1,3,5,7
    print(func(),type(func()))
  • 函数一旦遇到return就会立即退出函数(终止函数中的所有代码)

    def func():print("开始")for i in range(1,10):if i%2==0:print(i)else:returnprint("结束")
    func()# 输出
    开始
    

扩展:密码都不是明文。

  • 注册京东,京东存储:用户名和密码(密文)
  • 登录京东:用户名- 密码。

3.参数的补充

在函数基础部分,我们掌握函数和参数基础知识,掌握这些其实完全就可以进行项目的开发。补充内容包含:内存地址相关、面试题相关等,在特定情况下也可以让代码更加简洁,提升开发效率。

3.1 参数内存地址相关【面试题】

在开始开始讲参数内存地址相关之前,我们得先了解:使用 id查看下某个值的在内存中的地址

#查看某个值在内存中的地址
v='小峰'
print(id(v))

注:函数执行传参时,传递的是内存地址。

def func(data):print(data,id(data))
v='小峰'
print(id(v))
func(v)

Python参数的这一特性有两个好处:

  • 节省内存

  • 对于可变类型且函数中修改元素的内容,所有的地方都会修改。可变类型:列表、字典、集合。

def fun1(data):data.insert(2,0)print(id(data))
v1=[1,2,3,4] #列表
fun1(v1)
print(v1,id(v1))
############################
def fun2(data):data.add(8)print(id(data))
v2={1,2,3,4}#集合
fun2(v2)
print(v2,id(v2))
###########################
def fun3(data):data.update({"k4": 8})print(id(data))
v3={"k1":1,"k2":2,"k3":3} #字典类型
fun3(v3)
print(v3,id(v3))

提示注意:其他很多编程语言执行函数时,默认传参时会将数据重新拷贝一份,会浪费内存。.其他语言也可以通过 ref 等关键字来实现传递内存地址。当然,如果你不想让外部的变量和函数内部参数的变量一致,也可以选择将外部值拷贝一份,再传给函数。

def fun(data):print(data,id(data))
v=[1,2,3,4,5]
print(v,id(v))
new_v=copy.deepcopy(v)
fun(new_v)
print(new_v,id(new_v))
#结果:
[1, 2, 3, 4, 5] 2213990555712
[1, 2, 3, 4, 5] 2213990545664
[1, 2, 3, 4, 5] 2213990545664

3.2 函数的返回值是内存地址

def func():data = [11, 22, 33]return datav1 = func()
print(v1) # [11,22,33]

上述代码的执行过程:

  • 执行func函数
  • data = [11, 22, 33] 创建一块内存区域,内部存储[11,22,33],data变量指向这块内存地址。
  • return data 返回data指向的内存地址
  • v1接收返回值,所以 v1 和 data 都指向 [11,22,33] 的内存地址(两个变量指向此内存,引用计数器为2)
  • 由函数执行完毕之后,函数内部的变量都会被释放。(即:删除data变量,内存地址的引用计数器-1)

所以,最终v1指向的函数内部创建的那块内存地址。

3.3 参数的默认值【面试题】

这个知识点在面试题中出现的概率比较高,但真正实际开发中用的比较少。

def func(a1,a2=18):print(a1,a2)

> 原理:

        Python在创建函数(未执行)时,如果发现函数的参数中有默认值,则在函数内部会创建一块区域并维护这个默认值。 执行函数未传值时,则让a2指向 函数维护的那个值的地址。执行函数传值时,则让a2指向新传入的值的地址。在特定情况【默认参数的值是可变类型 list/dict/set】 & 【函数内部会修改这个值】下,参数的默认值 有坑 。

  • # 在函数内存中会维护一块区域存储
    def fun(a,b=[1,4,8]):b.append(100)print(a,b)print(id(a),id(b))
    fun(1)
    fun(2)
    fun(3,[1,2,3,4,5])输出结果
    1 [1, 4, 8, 100]
    1555535456560 1555542237248
    2 [1, 4, 8, 100, 100]
    1555535456592 1555542237248
    3 [1, 2, 3, 4, 5, 100]
    1555535456624 1555542227200
  • 大坑

    # 在内部会维护一块区域存储 [1, 2, 10, 20,40 ] ,内存地址 1010101010
    def func(a1, a2=[1, 2]):a2.append(a1)print(id(a2))return a2
    # a1=10
    # a2 -> 1010101010
    # v1 -> 1010101010
    v1 = func(10)
    print(v1,id(v1))  # [1, 2, 10]
    # a1=20
    # a2 -> 1010101010
    # v2 -> 1010101010
    v2 = func(20)
    print(v2,id(v2))  # [1, 2, 10, 20 ]
    # a1=30
    # a2 -> 11111111111        [11, 22,30]
    # v3 -> 11111111111
    v3 = func(30, [11, 22])
    print(v3,id(v3))  # [11, 22,30]
    # a1=40
    # a2 -> 1010101010
    # v4 -> 1010101010
    v4 = func(40)
    print(v4,id(v4))   # [1, 2, 10, 20,40 ]
    
  • 深坑

    # 内存中创建空间存储 [1, 2, 10, 20, 40] 地址:1010101010
    def func(a1, a2=[1, 2]):a2.append(a1)return a2
    # a1=10
    # a2 -> 1010101010
    # v1 -> 1010101010
    v1 = func(10)
    # a1=20
    # a2 -> 1010101010
    # v2 -> 1010101010
    v2 = func(20)
    # a1=30
    # a2 -> 11111111111   [11,22,30]
    # v3 -> 11111111111
    v3 = func(30, [11, 22])
    # a1=40
    # a2 -> 1010101010
    # v4 -> 1010101010
    v4 = func(40)print(v1) # [1, 2, 10, 20, 40]
    print(v2) # [1, 2, 10, 20, 40]
    print(v3) # [11,22,30]
    print(v4) # [1, 2, 10, 20, 40]
    

4. 函数和函数名

函数名其实就是一个变量,这个变量只不过代指的函数而已。

注意:函数必须先定义才能被调用执行(解释型语言)。

# 正确
def add(n1,n2):return n1 + n2ret = add(1,2)
print(ret) 

4.1 函数做元素

既然函数就相当于是一个变量,那么在列表等元素中是否可以把行数当做元素呢?

def func():return 123data_list = ["小峰", "func", func , func() ]print( data_list[0] ) # 字符串"小峰"
print( data_list[1] ) # 字符串 "func"
print( data_list[2] ) # 函数 func
print( data_list[3] ) # 整数 123res = data_list[2]()
print( res ) # 执行函数 func,并获取返回值;print再输出返回值。print( data_list[2]() ) # 123

注意:函数同时也可被哈希,所以函数名通知也可以当做 集合的元素、字典的键。

掌握这个知识之后,对后续的项目开发有很大的帮助,例如,在项目中遇到根据选择做不同操作时:

  • 情景1,例如:要开发一个类似于微信的功能。

    def send_message():"""发送消息"""passdef send_image():"""发送图片"""passdef send_emoji():"""发送表情"""passdef send_file():"""发送文件"""passdef xxx():"""收藏"""passfunction_dict = {"1": send_message,"2": send_image,"3": send_emoji,"4": send_file,"5": xxx
    }print("欢迎使用xx系统")
    print("请选择:1.发送消息;2.发送图片;3.发送表情;4.发送文件")
    choice = input("输入选择的序号") # "1"func = function_dict.get(choice)
    if not func:print("输入错误")
    else:# 执行函数func()
  • 情景2,例如:某个特定情况,要实现发送短信、微信、邮件。

    def send_msg():"""发送短信"""passdef send_email():"""发送图片"""passdef send_wechat():"""发送微信"""passfunc_list = [ send_msg, send_email, send_wechat ]
    for item in func_list:item()
    

上述两种情景,在参数相同时才可用,如果参数不一致,会出错。所以,在项目设计时就要让程序满足这一点,如果无法满足,也可以通过其他手段时间,例如:

情景:

def send_message(phone,content):"""发送消息"""passdef send_image(img_path, content):"""发送图片"""passdef send_emoji(emoji):"""发送表情"""passdef send_file(path):"""发送文件"""passfunction_dict = {"1": [ send_message,  ['15131255089', '你好呀']],"2": [ send_image,  ['xxx/xxx/xx.png', '消息内容']],"3": [ send_emoji, ["😁"]],"4": [ send_file, ['xx.zip'] ]
}print("欢迎使用xx系统")
print("请选择:1.发送消息;2.发送图片;3.发送表情;4.发送文件")
choice = input("输入选择的序号:") # 1item = function_dict.get(choice) # [ send_message,  ['15131255089', '你好呀']],
if not item:print("输入错误")
else:# 执行函数func = item[0] # send_messageparam_list = item[1] #  ['15131255089', '你好呀']func(*param_list) # send_message(*['15131255089', '你好呀'])

4.2 函数名赋值

  • 将函数名赋值给其他变量,函数名其实就个变量,代指某函数;如果将函数名赋值给另外一个变量,则此变量也会代指该函数,例如:

    def func(a1,a2):print(a1,a2)new_fuc = func# 此时,new_fuc和func都代指上面的那个函数,所以都可以被执行。
    func(1,1)
    new_fuc(2,2)
    
  • 对函数名重新赋值,如果将函数名修改为其他值,函数名便不再代指函数,例如:

    def func(a1,a2):print(a1,a2)# 执行func函数
    func(11,22)# func重新赋值成一个字符串
    func = "小峰"print(func)
    

    注意:由于函数名被重新定义之后,就会变量新被定义的值,所以大家在自定义函数时,不要与python内置的函数同名,否则会覆盖内置函数的功能。

4.3 函数名做参数和返回值

函数名其实就一个变量,代指某个函数,所以和其他的数据类型一样,也可以当做函数的参数和返回值。

  • 参数

    def plus(num):return num + 100def handler(func):res = func(10) # 110msg = "执行func,并获取到的结果为:{}".format(res)print(msg) # 执行func,并获取到的结果为:110# 执行handler函数,将plus作为参数传递给handler的形式参数func
    handler(plus)
    
  • 返回值

    def plus(num):return num + 100def handler():print("执行handler函数")return plusresult = handler()
    data = result(20) # 120
    print(data)
    

5. 作用域

作用域,可以理解为一块空间,这块空间的数据是可以共享的。通俗点来说,作用域就类似于一个房子,房子中的东西归里面的所有人共享其他房子的人无法获取

5.1 函数为作用域

        Python以函数为作用域,所以在函数内创建的所有数据,可以此函数中被使用,无法在其他函数中被使用。

def func():age = 20#局部变量,局部变量优先原则print(age)def handler():print(age)age=5#全局变量
func()
handler()
print(age)

5.2 全局和局部

Python中以函数为作用域,函数的作用域其实是一个局部作用域。

# 全局变量(变量名大写)
COUNTRY = "中国"
CITY_LIST = ["北京","上海","深圳"]def download():# 局部变量url = "http://www.xxx.com"

COUNTRYCITY_LIST是在全局作用域中,全局作用域中创建的变量称之为【全局变量】,可以在全局作用域中被使用,也可以在其局部作用域中被使用。download函数内部维护的就是一个局部作用域,在各自函数内部创建变量称之为【局部变量】,且局部变量只能在此作用域中被使用。局部作用域中想使用某个变量时,寻找的顺序为:优先在局部作用域中寻找,如果没有则去上级作用域中寻找。(局部变量优先的原则)

注意:全局变量一般都是大写。

示例1:在局部作用域中读取全局作用域的变量。

COUNTRY = "中国"
CITY_LIST = ["北京", "上海", "深圳"]def download():url = "http://www.xxx.com"print(url)print(COUNTRY)print(CITY_LIST)print(COUNTRY)
download()

示例2:局部作用域和全局作用域变量同名,局部变量优先

CITY_LIST = ["北京", "上海", "深圳"]def download():url = "http://www.xxx.com"CITY_LIST = ["河北", "河南", "山西"]print(url)print(CITY_LIST)print(CITY_LIST)
download()

5.3 global关键字

默认情况下,在局部作用域对全局变量只能进行:读取和修改内部元素(可变类型),无法对全局变量进行重新赋值。

  • 读取

    a=2
    def fun():print(a)  #对全局变量的读取fun()
  • 修改内部元素(可变类型)

    a=[2,"xiaofeng",(1,5)]
    print(a)
    def fun():a.append("liu")  #对内部元素的修改a[2]=3
    fun()
    print(a)
  • 无法对全局变量重新赋值

    a=2
    def fun():a=9print(a)
    fun() #9
    print(a) #2

如果想要在局部作用域中对全局变量重新赋值,则可以基于 global关键字实现,例如:

a=2
def fun():global aa=9print(a)
print(a)
fun()
print(a)

三、函数的进阶

  • 函数的嵌套
  • 闭包
  • 装饰器

上述内容均属于函数部分必备知识,以后开发时直接和间接都会使用,请务必理解(重在理解,不要去死记硬背)。

1. 函数嵌套

Python中以函数为作用域在作用域中定义的相关数据只能被当前作用域或子作用域使用

1.1 函数在作用域中

其实,函数也是定义在作用域中的数据,在执行函数时候,也同样遵循:优先在自己作用域中寻找,没有则向上一接作用域寻找,例如:

# 1. 在全局作用域定义了函数func
def func():print("你好")# 2. 在全局作用域找到func函数并执行。
func()# 3.在全局作用域定义了execute函数
def execute():print("开始")# 优先在当前函数作用域找func函数,没有则向上级作用域中寻找。func()print("结束")# 4.在全局作用域执行execute函数
execute()

1.2 函数定义的位置

函数不仅可以定义在全局作用域中,其实函数也可以定义在局部作用域,这样函数被局部作用域和其子作用于中调用(函数的嵌套)。

def func(a):print("开始")def sum(a):return a+2def sub(a):return a-2if a>3:return sum(a)else:return sub(a)print(func(2))
print(func(4))

到现在你会发现,只要理解数据定义时所存在的作用域,并根据从上到下代码执行过程进行分析,再怎么嵌套都可以搞定。有没有想过为什么要这么嵌套定义?把函数都定义在全局不好吗?

其实,大多数情况下我们都会将函数定义在全局,不会嵌套着定义函数。不过,当我们定义一个函数去实现某功能,想要将内部功能拆分成N个函数,又担心这个N个函数放在全局会与其他函数名冲突时(尤其多人协同开发)可以选择使用函数的嵌套

def f1():passdef f2():passdef func():f1()f2()

1.3 嵌套引发的作用域问题

基于内存和执行过程分析作用域。

name = "xiaofeng"
def run():name = "alex"def inner():print(name)def test():print("hello")return [inner, test]
func_list = run()
func_list[0]()
func_list[1]()

三句话搞定作用域:

  • 优先在自己的作用域找,自己没有就去上级作用域。
  • 在作用域中寻找值时,要确保此次此刻值是什么。
  • 分析函数的执行,并确定函数作用域链。(函数嵌套)

2.闭包

闭包,简而言之就是将数据封装在一个包(区域)中,使用时再去里面取。(本质上闭包是基于函数嵌套搞出来一个中特殊嵌套

  • 闭包应用场景1:封装数据防止污染全局。

    def func(age):name = "xiaofeng"def f1():print(name, age)def f2():print(name, age)f1()f2()
    func(123)
    
  • 闭包应用场景2:封装数据封到一个包里,使用时在取。 

    def task(src):def inner():print(src)return innertask('hello')()
    

3.装饰器

现在给你一个函数,在不修改函数源码的前提下,实现在函数执行前和执行后分别输入 “before” 和 “after”。

def func():print("我是func函数")value = (11,22,33,44) return valueresult = func()
print(result)

3.1 装饰器的引入

  • 一般刚开始学编程的实现思路:
def func():print("before")print("我是func函数")value = (11,22,33,44)     print("after")    return valueresult = func()
  • 更高级的的实现思路:
def func():print("我是func函数")value = (11, 22, 33, 44)return value
def outer(origin):def inner():print('inner')origin()print("after")return innerfunc = outer(func)
result = func()
  • 再对其进行优化后的思路,即就是处理返回值:
def func():print("我是func函数")value = (11, 22, 33, 44)return value
def outer(origin):def inner():print('inner')res = origin()print("after")return res  #保持和原函数一样的效果return innerresult = outer(func)()

3.2 装饰器的基本语法结构

在Python中有个一个特殊的语法糖,即就是本讲所说的装饰器:

def outer(origin):def inner():print('before')res = origin()print("after")return resreturn inner@outer
def func():print("我是func函数")value = (11, 22, 33, 44)return valuefunc()

3.3 装饰器在多函数中的应用

请在这3个函数执行前和执行后分别输入 “before” 和 “after”

def func1():print("我是func1函数")value = (11, 22, 33, 44)return value        
def func2():print("我是func2函数")value = (11, 22, 33, 44)return value 
def func3():print("我是func3函数")value = (11, 22, 33, 44)return value   
  • 学完装饰器的实现思路:
def outer(org):def inner():print("before")res = org()print("after")return resreturn inner@outer
def func1():print("我是func1函数")value = (11, 22, 33, 44)return value@outer
def func2():print("我是func2函数")value = (11, 22, 33, 44)return value@outer
def func3():print("我是func3函数")value = (11, 22, 33, 44)return valuefunc1()
func2()
func3()

装饰器在不修改原函数内容的前提下通过@函数可以实现在函数前后自定义执行一些功能(批量操作会更有意义)

3.4 装饰器的再优化,语法结构的改良

优化以支持多个参数的情况。

def outer(origin):def inner(*args, **kwargs):print("before 110")res = origin(*args, **kwargs)  # 调用原来的func函数print("after")return resreturn inner@outer  # func1 = outer(func1)
def func1(a1):print("我是func1函数")value = (11, 22, 33, 44)return value@outer  # func2 = outer(func2)
def func2(a1, a2):print("我是func2函数")value = (11, 22, 33, 44)return valuefunc1(1)
func2(11, a2=22)
  • 实现原理基于@语法和函数闭包,将原函数封装在闭包中,然后将函数赋值为一个新的函数(内层函数),执行函数时再在内层函数中执行闭包中的原函数

  • 实现效果:可以在不改变原函数内部代码 和 调用方式的前提下,实现在函数执行和执行扩展功能。

  • 适用场景:多个函数系统统一在执行前后自定义一些功能。

3.5 重要补充

       装饰器实际上就是将原函数更改为其他的函数,然后再此函数中再去调用原函数。其实,一般情况下大家不用 functools 也可以实现装饰器的基本功能,但后期在项目开发时,不加 functools 会出错( 内部会读取__name__,且__name__重名的话就报错 ,所以在此大家就要规范起来自己的写法。 functools是 Python 标准库中的一个模块,提供了对高阶函数(即操作或返回其他函数的函数)的支持。它包含了一些常用的函数装饰器和工具,用于简化函数操作和优化代码。

  • 获取函数名
def test():pass
print(test.__name__) # testdef auth(func):def inner(*args, **kwargs):return func(*args, **kwargs)return inner@auth
def test():pass
test()
print(test.__name__) # inner
import functoolsdef auth(func):@functools.wraps(func)def inner(*args, **kwargs):return func(*args, **kwargs)return inner@auth
def handler():passhandler()
print(handler.__name__)  # handler
def auth(func):@functools.wraps(func)def inner(*args, **kwargs):"""巴巴里吧"""res = func(*args, **kwargs)  # 执行原函数print(args)print(kwargs)return resreturn inner
@auth
def func(*args, **kwargs):passprint(func(1,2,name="xiaofeng"))
print(func.__name__)

4. 匿名函数

传统的函数的定义包括了:函数名 + 函数体匿名函数则是基于lambda表达式实现定义一个可以没有名字的函数,在编写匿名函数时,由于受限 函数体只能写一行,所以匿名函数只能处理非常简单的功能。基于Lambda定义的函数格式为:lambda 参数:函数体

例如:

data_list = [ lambda x:x+100,  lambda x:x+110, lambda x:x+120 ]print( data_list[0] )
  • 参数,支持任意参数。

    lambda x: 函数体
    lambda x1,x2: 函数体
    lambda *args, **kwargs: 函数体
    
  • 函数体,只能支持单行的代码。

  • 返回值,默认将函数体单行代码执行的结果返回给函数的执行处。

    func = lambda x: x + 100v1 = func(10)
    print(v1) # 110
    

注:匿名函数适用于简单的业务处理,可以快速并简单的创建函数。

补充:三元运算

简单的函数,可以基于lambda表达式实现。简单的条件语句,可以基于三元运算实现

# 结果 =  条件成立时    if   条件   else   不成立
例如:

num=int(input("Enter a number:"))
print("hello") if num==1 else print("goodbye")

lambda表达式和三元运算没有任何关系,属于两个独立的知识点。但是掌握三元运算之后,以后再编写匿名函数时,就可以处理再稍微复杂点的情况了,例如:

#匿名函数,lambda结合三元运算就可以实现比较复杂的功能
func = lambda x: "大了" if x > 66 else "小了"
print(func(1)) # "小了"
print(func(100)) # "大了"

5. 生成器

        生成器是由 函数+yield关键字 创造出来的写法,在特定情况下,用他可以帮助我们节省内存。

  • 生成器函数,函数中有yield存在时,这个函数就是生产生成器函数。

    def func():print(111)yield 1
    
  • 生成器对象,执行生成器函数时,会返回一个生成器对象。

    def func():print(111)yield 1print(222)yield 2print(333)yield 3print(444)data = func()
    v1 = next(data)
    print(v1)
    v2 = next(data)
    print(v2)
    v3 = next(data)
    print(v3)
    v4 = next(data)
    print(v4) # 执行生成器函数func,返回的生成器对象。
    # 注意:执行生成器函数时,函数内部代码不会执行。 结束或中途遇到return,程序提示StopIteration错误
    

        生成器的特点是,记录在函数中的执行位置,下次执行next时,会从上一次的位置基础上再继续向下执行。

应用场景:

        当以后需要我们在内存中创建很多数据时,可以想着用基于生成器来实现一点一点生成(用一点生产一点),以节省内存的开销。

扩展:send()

def func():print(111)v1 = yield 1print(v1)print(222)v2 = yield 2print(v2)print(333)data = func()
n1 = data.send(None)
print(n1)
n2 = data.send(666)
print(n2)
n3 = data.send(777)

send方法的工作原理

  1. 生成器函数在遇到yield语句时会暂停执行,并返回yield后面的值。
  2. 调用send方法时,生成器会从上次暂停的地方继续执行,并将send方法的参数作为yield表达式的结果。
  3. 生成器继续执行,直到遇到下一个yield语句或函数结束。

注意事项

  • 在第一次调用生成器时,不能直接使用send方法,因为生成器还没有执行到第一个yield语句。通常需要先调用next方法或send(None)来启动生成器。
  • 如果生成器已经结束(即没有更多的yield语句),再调用send方法会抛出StopIteration异常。

6.内置函数

Python内部为我们提供了很多方便的内置函数,在此整理出来36个给大家来讲解。

  • 第1组

#内置函数
#abs 求绝对值
print(abs(-1))
#pow指数
print(pow(2,3))
#sum 求和
print(sum([1,4,9]))
#divmod 求商和余数
print(divmod(7,4))
#min 求最小值
print(min([1,8,-2]))
#max 求最大值
print(max([1,8,-2]))
#any 是否存在为真
print(any([False,0,'']))
#all 是否全为真
print(all([1,2,3]))#十进制转化为二进制
print(bin(10))
#十进制转化为八进制
print(oct(10))
#十进制转化为十六进制
print(hex(10))
# ord,获取字符对应的unicode码点(十进制)
print(ord('A'))
# chr,根据码点(十进制)获取对应字符
print(chr(ord('A')+1))

  • 第2组,数据类型中有讲到

int、foat、str,unicode编码、bytes,utf-8、gbk编码、bool、list、dict、tuple、set

  • 第3组(13个)

    len、print、input、open、type,获取数据类型、range、id
  • 补充:
  • enumerate

    #enumerate  枚举
    #语法:enumerate(sequence, [start=0])
    v1 = ["小峰", "alex", 'root']
    for num, value in enumerate(v1, 1):print(num, value)# hash 它用于获取一个对象的哈希值。哈希值是一个固定长度的整数,用于表示一个对象的状态或标识,通常用于构建字典、集合等数据结构,以及进行数据加密等方面。
    print(hash("xiaofeng"))#callable,是否可执行,后面是否可以加括号。
    #通常用来判断是否为函数
    def func():print("Hello World")
    v=1
    print(callable(func))
    print(callable(v))#zip
    # Python 3:zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。我们可以使用 list() 转换来输出列表
    v1=(1,5,8,3)
    v2=(5,71,1,0)
    v3=(20,4,6,9,39)
    print(zip(v1,v2,v3))#返回的是一个对象,最后一列不全,所以剔除掉
    for i in zip(v1,v2,v3):print(i)
  • sorted,排序

    #eg1:
    print(sorted([1,7,0,-2,7]))  #由小到大的排序
    print(sorted([1,7,0,-2,7],reverse=True))  #由大到小的排序#eg2:
    info = {"wupeiqi": {'id': 10,'age': 119},"root": {'id': 20,'age': 29},"seven": {'id': 9,'age': 9},"admin": {'id': 11,'age': 139},
    }
    result = sorted(info.items(), key=lambda x: x[1]['age'])
    print(result)
    
    data_list = ['1-5 编译器和解释器.mp4','1-17 今日作业.mp4','1-9 Python解释器种类.mp4','1-16 今日总结.mp4','1-2 课堂笔记的创建.mp4','1-15 Pycharm使用和破解(win系统).mp4','1-12 python解释器的安装(mac系统).mp4','1-13 python解释器的安装(win系统).mp4','1-8 Python介绍.mp4', '1-7 编程语言的分类.mp4','1-3 常见计算机基本概念.mp4','1-14 Pycharm使用和破解(mac系统).mp4','1-10 CPython解释器版本.mp4','1-1 今日概要.mp4','1-6 学习编程本质上的三件事.mp4','1-18 作业答案和讲解.mp4','1-4 编程语言.mp4','1-11 环境搭建说明.mp4'
    ]
    result = sorted(data_list, key=lambda x: int(x.split(' ')[0].split("-")[-1]) )
    print(result)
    

7.推导式

        推导式是Python中提供了一个非常方便的功能,可以让我们通过一行代码实现创建list、dict、tuple、set 的同时初始化一些值。请创建一个列表,并在列表中初始化:0、1、2、3、4、5、6、7、8、9…299 整数元素。

  • 列表

    对列表的初始化
    num_list=[i for i in range(10)]num_list=(i,i,i) for i in range(10)结合三元运算对列表进行初始化
    num_list=[i for i in range(10) if i%2==0]
  • 集合

    num_set1 = { i for i in range(10)}
    num_set2 = { (i,i,i) for i in range(10)}
    num_set3 = { (i,i,i) for i in range(10) if i%2==0 }
  • 字典

    num_dict1 = { i:i for i in range(10)}
    num_dict2 = { i:(i,11) for i in range(10)}
    num_dict3 = { i:(i,11) for i in range(10) if i>7}
  • 元组,不同于其他类型。

        不会立即执行内部循环去生成数据,而是得到一个生成器对象。

data = (i for i in range(10))
print(data)
for item in data:print(item)
  • 看代码写结果(新浪微博面试题)

    data_list = [lambda x: x + i for i in range(10)]  # [函数,函数,函数]   i=9v1 = data_list[0](100)
    v2 = data_list[3](100)
    print(v1, v2)  # 109 109
    

补充:

  1. 推导式支持嵌套

    # 一副扑克牌poker_list = [ (color,num) for num in range(1,14) for color in ["红桃", "黑桃", "方片", "梅花"]]
    print(poker_list)	
  2. 烧脑面试题

    def num():return [lambda x: i * x for i in range(4)]
    # 1. num()并获取返回值  [函数,函数,函数,函数] i=3 ,即就是相同的函数和相同的i
    # 2. for循环返回值
    # 3. 给每个函数传参都是2
    result = [m(2) for m in num()]  # [6,6,6,6]
    print(result)
    def num():return (lambda x: i * x for i in range(4))# 1. num()并获取返回值  生成器对象
    # 2. for循环返回值
    # 3. 返回值的每个元素(2)
    result = [m(2) for m in num()]  # [0,2,4,6 ]
    print(result)
    

 本   篇   完   结   …  …


持     续     更     新     中   …    … 

 

相关文章:

Python函数——万字详解

—— 小 峰 编 程 导 语: 从今天开始,我们将进入第二模块的学习——函数。第一模块主要是学习python基础知识,从第二模块开始就可以通过程序去解决工作中实际的问题。从今天开始,我们将进入第二模块的学习,此模块…...

es在已有历史数据的文档新增加字段操作

新增字段设置默认值 场景 在已经有大量数据的索引文档上,增加新字段 技术实现 一.更新索引映射 通过PUT请求显式定义新字段类型,确保后续写入的文档能被正确解析 PUT /文档名/_mapping {"properties": {"字段名1": {"type…...

LeetCode 35 搜索插入位置题解

LeetCode 35 搜索插入位置题解 题目描述 题目链接 给定一个排序数组和一个目标值,在数组中找到目标值并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置(需保证数组仍然有序)。要求时间复杂度为 O(log n)。…...

RabbitMQ通信模式(Simplest)Python示例

RabbitMQ通信模式-Python示例 0.RabbitMQ官网通信模式1.Simplest(简单)模式1.1 发送端1.2 接收端 0.RabbitMQ官网通信模式 1.Simplest(简单)模式 1.1 发送端 # -*- coding: utf-8 -*- """ Author: xxx date: 2025/5/19 11:30 Description: Simaple简单模…...

游戏开发实战(一):Python复刻「崩坏星穹铁道」嗷呜嗷呜事务所---源码级解析该小游戏背后的算法与设计模式【纯原创】

文章目录 奇美拉项目游戏规则奇美拉(Chimeras)档案领队成员 结果展示: 奇美拉项目 由于项目工程较大,并且我打算把我的思考过程和实现过程中踩过的坑都分享一下,因此会分3-4篇博文详细讲解本项目。本文首先介绍下游戏规则并给出奇美拉档案。…...

力扣热题100之删除链表的倒数第N个节点

题目 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 代码 方法一 将链表中的值放入列表中,然后删除倒数第n个值,再将剩下的数依次转化为链表 # Definition for singly-linked list. # class ListNode: # …...

OCframework编译Swift

建一个OC的framework: 需要对外暴露的OC文件,需要放到OC的.h文件中 framework中,OC类,调用framework中的Swift类: #import "WowAudioFocus/WowAudioFocus-Swift.h" //02 #import "{工程名}/{工程…...

【AI News | 20250519】每日AI进展

AI Repos 1、deepdrone DeepDrone是一款基于smolagents框架的无人机聊天代理,集成DroneKit实现无人机分析与操作。用户可通过自然语言聊天与无人机助手交互,实现飞行路径和传感器数据可视化、基于飞行时长的维护建议、任务规划以及真实的无人机控制&…...

分布式ID生成系统

代码地址: github mid 简介 分布式 ID 生成系统是一个高性能、可靠的 ID 生成服务,支持两种模式:Snowflake(基于时间戳的内存生成)和 Segment(基于 MySQL 的号段分配)。系统采用双 Buffer 策略优化性能,集成 Prometheus 监控和 Zap 结构化日志,确保高可用性和可观测性…...

MAC常用操作整理

音量方法: 电脑键盘的右上角就有静音和不静音的按钮,还有调节音量的按钮,调节屏幕亮度的按钮 切换输入法方法: 1.大写按键,2.function按键(fn), 3.control 空格键, 选择上一个输入法,4.controloption空格…...

【Canvas与图标】圆角方块蓝星CSS图标

【成图】 120*120的png图标 大小图&#xff1a; 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>圆角方块蓝星CSS Draft1</…...

易境通散货拼柜系统:提高货代企业货物配载效率

在国际物流代理运输领域&#xff0c;货物配载是整个供应链的核心环节&#xff0c;其优化对于提升整个供应链的效率至关重要。传统的配载管理方式往往依赖人工操作&#xff0c;不仅效率低下&#xff0c;还容易出现错误。面对多订单、多货主、多目的地的复杂场景&#xff0c;传统…...

[Spring Boot]整合Java Mail实现Outlook发送邮件

日常开发过程中,我们经常需要使用到邮件发送任务,比方说验证码的发送、日常信息的通知等。日常比较常用的邮件发送方包括:163、QQ等,本文主要讲解Outlook SMTP的开启方式、OutLook STARTTTL的配置、如何通过JavaMail来实现电子邮件的发送等。 Outlook作为微软提供的企业电子…...

【盈达科技】GEO优化实战策略

提升内容在生成式引擎中的可见性&#xff1a;实战策略 随着生成式引擎&#xff08;Generative Engines, GEs&#xff09;的兴起&#xff0c;内容创作者面临着新的挑战和机遇。这些引擎通过整合和总结多源信息来提供精准且个性化的回答&#xff0c;正在迅速取代传统搜索引擎。为…...

HTTP 协议基础

本篇文章会从如下角度介绍 HTTP 协议&#xff1a; 原理与工作机制请求方法与状态码Header 与 Body 1、原理与工作机制 1.1 HTTP 是什么 HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff0c;"超"表示扩展而非超级&#xff0c;即可以链接到其他文本…...

ros运行包,Ubuntu20.04成功运行LIO-SAM

zz:~/lio_sam_ws$ source devel/setup.bash zz:~/lio_sam_ws$ roslaunch lio_sam run.launch 创建包链接&#xff1a; 链接1&#xff1a;Ubuntu20.04成功运行LIO-SAM_ubuntu20.04运行liosam-CSDN博客 链接2&#xff1a;ubuntu 20.04 ROS 编译和运行 lio-sam,并且导出PCD文件…...

Linux《自主Shell命令行解释器》

在上一篇的进程控制当中我们已经了解了进程退出、进程等待以及进程替换的相关概念&#xff0c;那么在了解了这些的概念之后接下来在本篇当中我们就可以结合之前我们学习的知识来实现一个自主的Shell命令行解释器&#xff0c;通过Shell的实现能让我们进一步的理解操作系统当中的…...

设置IDEA打开新项目使用JDK17

由于最近在学习Spring-AI&#xff0c;所以JDK8已经不适用了&#xff0c;但是每次创建新项目都还是JDK8&#xff0c;每次调来调去很麻烦 把Projects和SDKs都调整为JDK17即可 同时&#xff0c;Maven也要做些更改&#xff0c;主要是添加build标签 <build><plugins>&…...

Vue百日学习计划Day36-42天详细计划-Gemini版

总目标: 在 Day 36-42 理解组件化开发的思想&#xff0c;熟练掌握 Vue 组件的注册、Props、Events、v-model、Slots、Provide/Inject 等核心概念和实践&#xff0c;能够构建可复用和易于维护的组件结构。 所需资源: Vue 3 官方文档 (组件基础): https://cn.vuejs.org/guide/es…...

Python对JSON数据操作

在Python中&#xff0c;对JSON数据进行增删改查及加载保存操作&#xff0c;主要通过内置的json模块实现。 一、基础操作 1. 加载JSON数据 • 从文件加载 使用json.load()读取JSON文件并转换为Python对象&#xff08;字典/列表&#xff09;&#xff1a; import json with open…...

upload靶场1-5关

网上的解析有一些题目对应不上&#xff0c;比如第五关说是 空格 点 空格绕过 &#xff0c;我这里就无法成功解析&#xff0c;但大小写绕过就成功了&#xff0c;慢慢会把后面的关卡也写出来 这里建议开一台win7的虚拟机&#xff0c;在上面搭建靶场&#xff0c;可以省很多麻烦 …...

网络传输(ping命令,wget命令,curl命令),端口

网络传输&#xff1a; ping命令&#xff1a;检查指定的网络服务器是否是可联通状态 语法&#xff1a;ping 【-c num】IP或主机名 -c&#xff1a;是检查的次数&#xff0c;不使用-c&#xff0c;将无限次持续检查 wget命令&#xff1a;wget是非交互式的文件下载器&#xff0…...

upload-labs靶场通关详解:第10关

一、分析源代码 $is_upload false; $msg null; if (isset($_POST[submit])) {if (file_exists(UPLOAD_PATH)) {$deny_ext array(".php",".php5",".php4",".php3",".php2",".html",".htm",".ph…...

深入解析`lsof`命令:查看系统中打开文件与进程信息

1、lsof的基本概念 lsof &#xff08;List Open Files&#xff09; 提供了一种方式来查看系统上哪些进程正在访问哪些文件&#xff0c;能够显示文件类型、文件名、文件描述符、所属进程等详细信息。 在类Unix系统中&#xff0c;几乎所有的操作都与文件相关联&#xff0c;文件不…...

C++ 与 Python 内存分配策略对比

内存管理是编程中的一个核心概念&#xff0c;它直接影响程序的性能、稳定性和资源利用率。C 和 Python 作为两种广泛使用的编程语言&#xff0c;在内存分配和管理方面采用了截然不同的策略。 C 内存分配策略 C 赋予程序员对内存的精细控制能力&#xff0c;同时也带来了更大的…...

TB开拓者策略交易信号闪烁根因及解决方法

TB开拓者策略信号闪烁分析 TB开拓者策略交易信号闪烁根因 TB开拓者策略交易信号闪烁根因分析 信号闪烁是交易策略开发中常见的问题&#xff0c;特别是在TB(TradeBlazer)开拓者等平台上。以下是信号闪烁的主要根因分析&#xff1a; 主要根因 未来函数问题 使用了包含未来信息…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(24):受身形

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(24):受身形 1、前言(1)情况说明(2)工程师的信仰2、知识点(1)うけみけい 受身形(2)復習(ふくしゅう):3、单词(1)日语(2)日语片假名单词4、相近词练习5、单词辨析记录6、总结1、前言 (1)情况说明 自己在今…...

牛客网NC209794:使徒袭来

牛客网NC209794:使徒袭来 题目背景 问题分析 数学建模 设三位驾驶员的战斗力分别为 a, b, c已知条件&#xff1a;a b c n (n为输入的正整数)目标&#xff1a;求 a b c 的最小值 解题思路 根据算术-几何平均值不等式(AM-GM不等式)&#xff0c;对于任意正实数a, b, c&a…...

命令行登录 MySQL 报 Segmentation fault 故障解决

问题描述&#xff1a;对 mysql8.0.35 源码进行 make&#xff0c;由于一开始因为yum源问题少安装依赖库 库&#xff0c;在链接时遇到错误 undefined reference to&#xff0c;后来安装了相关依赖库&#xff0c;再次 make 成功。于是将 mysqld 启动&#xff0c;再用 mysql -u roo…...

2025ICPC邀请赛南昌游记

滚榜时候队伍照片放的人家的闹麻了&#xff0c;手机举了半天 。 最后银牌700小几十罚时&#xff0c;rank60多点。 参赛体验还行&#xff0c;队长是福建人&#xff0c;说感觉这个热度是主场作战哈哈哈哈。空调制冷确实不太行吧。 9s过A是啥&#xff0c;没见过&#xff0c;虽然…...

kotlin flow的写法

以下是 Android 开发中 Kotlin Flow 的常见使用模式和操作符的完整中文总结&#xff1a; 1. 基本 Flow 创建方式 // 从多个值创建 val flow1 flowOf(1, 2, 3)// 使用 flow 构建器 val flow2 flow {emit(1)delay(100)emit(2) }// 从集合创建 val flow3 listOf(1, 2, 3).asFl…...

springboot+mybatis或mybatisplus在进行%name%的前后模糊查询时如何放防止sql注入

在使用 Spring Boot 配合 MyBatis 或 MyBatis-Plus 进行数据库操作时&#xff0c;确保防止 SQL 注入是非常重要的。对于 %name% 样式的前后模糊查询&#xff0c;以下是几种有效的方法来防止 SQL 注入&#xff1a; 1. 使用 MyBatis 的 <if> 标签和 #{} 占位符 MyBatis 默…...

基于51单片机教室红外计数灯光控制—可蓝牙控制

基于51单片机智能教室灯光 &#xff08;仿真&#xff0b;程序&#xff0b;原理图&#xff0b;PCB&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 本系统由STC89C52单片机时钟芯片DS1302液晶屏LCD1602光敏电阻红外对管LED灯模块按键模块蓝牙模块构成 具体…...

HTTPS、SSL证书是啥?网站“安全小锁”的入门科普

你有没有发现&#xff0c;浏览网页时&#xff0c;有些网站地址栏前面会出现一个小锁的图标&#x1f512;&#xff0c;而有些网站却没有&#xff1f;这个小锁其实代表着网站用了“HTTPS”&#xff0c;是比普通“HTTP”更安全的协议。今天&#xff0c;我们就来聊聊HTTPS、SSL证书…...

大模型备案中的安全考量:筑牢数字时代的安全防线

在数字化浪潮席卷全球的当下&#xff0c;大模型技术凭借强大的数据分析、模式识别与语言理解生成能力&#xff0c;成为推动产业变革、提升社会运转效率的关键力量。从智能客服降本增效&#xff0c;到医疗影像精准诊断&#xff0c;再到金融风险智能预测&#xff0c;大模型正重塑…...

Linux句柄数过多问题排查

以下是Linux句柄数过多问题的排查与解决方法整理&#xff1a; 一、检测句柄使用情况 1‌.查看系统限制‌ 单个进程限制&#xff1a;ulimit -n 系统级总限制&#xff1a;cat /proc/sys/fs/file-max 2‌.统计进程占用量‌ 查看指定进程&#xff1a;lsof -p <PID> | wc -…...

Python训练第三十天

DAY 30 模块和库的导入 知识点回顾&#xff1a; 导入官方库的三种手段导入自定义库/模块的方式导入库/模块的核心逻辑&#xff1a;找到根目录&#xff08;python解释器的目录和终端的目录不一致&#xff09; 总结&#xff1a;导入包的核心就是找到目录&#xff0c;只有理解了py…...

Java资源管理与防止泄漏:从SeaTunnel源码看资源释放

资源管理是 Java 开发中常被忽视却至关重要的一环。本文从 SeaTunnel 案例出发&#xff0c;探讨 Java 中如何正确管理资源&#xff0c;防止资源泄漏。 SeaTunnel 中的一次修复 Apache SeaTunnel 项目中的 HiveSink 组件曾存在一个典型的资源泄漏隐患。修复前后的代码对比如下…...

Notepad++ 学习(三)使用python插件编写脚本:实现跳转指定标签页(自主研发)

目录 一、先看成果二、安装Python Script插件三、配置Python脚本四、使用脚本跳转标签页方法一&#xff1a;通过菜单运行方法二&#xff1a;设置快捷键&#xff08;推荐&#xff09; 五、注意事项六、进阶使用 官网地址&#xff1a; https://notepad-plus-plus.org/Python Scri…...

PYTHON训练营DAY30

库的导入 一、导入整个 import 库 二、从库中导入特征项 from 库 import XXX 三、非标准导入&#xff1a;导入整个库 from 库 import * 四、导入自定义的库 &#xff08;一&#xff09;项目 创建一个打招呼的库 # greet.py def say_hello(name):return f"你好&a…...

Linux 文件(2)

文章目录 1. 文件描述符1.1 文件描述符是什么1.2 文件描述符如何分配 2 重定向2.1 输出重定向2.2 输入重定向2.3 使用dup2进行重定向 3. 文件、父子进程和进程替换 1. 文件描述符 1.1 文件描述符是什么 什么是文件描述符呢&#xff1f; 我们先来看之前所介绍的系统级别的文件…...

netcore项目使用winforms与blazor结合来开发如何按F12,可以调出chrome devtool工具辅助开发

就是像在开发网页那样&#xff0c;可以使用devtool工具辅助开发。可查看页面css&#xff0c;js等。我在网上看解决办法。没一个有用的。自己找了一个。不需要单独在页面写多余的代码 我的program.cs中有服务注册代码增加 3行代码。 #if DEBUGservices.AddBlazorWebViewDevelo…...

CSS attr() 函数详解

attr() 是 CSS 中的一个函数&#xff0c;用于获取 HTML 元素的属性值并在样式中使用。虽然功能强大&#xff0c;但它的应用有一些限制和注意事项。 基本语法 element::pseudo-element {property: attr(attribute-name); } 可用场景 1. 在伪元素的 content 属性中使用&#…...

人生如戏、戏如人生

今早&#xff0c;6&#xff1a;30起床给一家人弄早餐&#xff0c;然后听到了老公的一声大喊&#xff1a;”半小时了&#xff0c;你干什么了“&#xff0c;原来孩子说她在理书包&#xff0c;被老公骂了。 最近几天&#xff0c;老公脾气变得很差&#xff0c;孩子每天都会被老公骂…...

Java迭代器知识点详解

在 Java 编程中&#xff0c;迭代器&#xff08;Iterator&#xff09;是一种用于遍历集合&#xff08;如 List、Set、Map 等&#xff09;元素的接口。它提供了一种统一的方式来访问集合中的元素&#xff0c;而无需暴露集合的内部结构。以下是关于 Java 迭代器的详细知识点&#…...

免费开放试乘体验!苏州金龙自动驾驶巴士即将上线阳澄数谷

近日&#xff0c;苏州自动驾驶巴士线路——阳澄数谷示范线正式上线&#xff0c;即日起向全民免费开放试乘体验&#xff01; 在苏州工业园区地铁3号线倪浜•阳澄数谷站外&#xff0c;一辆辆黑、白配色的小巴正在道路上有条不紊地行驶。与普通公交不同的是&#xff0c;小巴造型奇…...

Kotlin 协程

第一个协程程序 协程是可暂停计算的一个实例。它在概念上类似于线程&#xff0c;因为它需要运行一个代码块&#xff0c;该代码块与其他代码并发运行。然而&#xff0c;协程并不绑定到任何特定的线程。它可以在一个线程中暂停执行&#xff0c;并在另一个线程中恢复执行。 协程…...

MySQL函数触发:函数处理与触发器自动化应用

引言 各位数据库爱好者们好&#xff01;今天我们要探索MySQL中两个强大的自动化工具——函数和触发器 &#x1f680;。函数就像数据库中的"瑞士军刀"&#xff0c;能帮你高效处理各种数据&#xff1b;而触发器则是数据库的"自动感应器"&#xff0c;能在数据…...

数据可视化热图工具:Python实现CSV/XLS导入与EXE打包

在数据分析工作中,热图(Heatmap)是一种非常直观的可视化工具,能够清晰展示数据矩阵中的数值分布和相关性。本文将介绍如何使用Python构建一个支持CSV/XLS文件导入、热图生成并可打包为EXE的桌面应用程序。 核心功能设计 我们的热图工具将包含以下核心功能: 支持CSV和Excel…...

CUDA Stream的进阶用法:流水线并行的资源竞争解决方案

点击 “AladdinEdu&#xff0c;同学们用得起的【H卡】算力平台”&#xff0c;H卡级别算力&#xff0c;按量计费&#xff0c;灵活弹性&#xff0c;顶级配置&#xff0c;学生专属优惠。 引言&#xff1a;多任务推理场景的挑战 GPU在AI推理服务器的典型负载特征&#xff08;并行模…...