Python函数(超详细解释)函数参数类型 、闭包、 装饰器、 lambda表达式 、生成器 递归函数、函数文档、类型注释、内省、高阶函数(函数程编程) 语法糖、偏函数 文章持续更新中,看我敲那么多字的份上,点个赞,收个藏,关个注吧,球球啦!!!
目录
例02 main(课讲例题)(在作为模块导人时,测试代码并不会运行。)
例02 装饰器的写法:语法糖(@time_master更好的易用性、简洁性、可读性和便捷性)
例03 多个装饰器同时用在同一个函数上(注意执行的顺序,从装饰器的编写方式倒这调用)
函数的认识(name用于测试函数)
例01 函数(def关键字用于定义一个新的函数)
myfunc()
def myfunc():
for i in range(3):
print("I am zmr")
myfunc()
I am zmr
I am zmr
I am zmr
def myfunc(name):
for i in range(3):
print(f"I am {name}.")
myfunc("zmr")
I am zmr.
I am zmr.
I am zmr.
def myfunc(name,times):
for i in range(times):
print(f"i am {name}")
myfunc("hahha",3)
i am hahha
i am hahha
i am hahha
例02 main(课讲例题)(在作为模块导人时,测试代码并不会运行。)
#可以用来测试其他程序导入此函数是否成功
# 当此代码中定义了很多的函数后,if语句的必要性可以使此代码中的函数不影响到其将被导入的模块
def func():
print("__name =",__name__)
if __name__ == "__main__":
func()
#现在只执行一遍
from text01 import func
func()
将函数保存成文件 变量__name_-(前后分别有两个下划线)是Python提供的特殊变量。如果使用导人模块的 方法调用脚本,这个变量的值就是模块名;如果直接运行脚本,这个变量的值就是__main__。 这里定义了仅当变量-_name_-等于_main_ 时(即直接调用时)才运行的代码。因此, 我们可以在这个代码块中写入测试代码,以测试模块的行为。 正如我们在本节体验5中看到的那样,在作为模块导人时,测试代码并不会运行。
函数参数的类型
位置参数,关键字参数,默认参数,收集参数
# 位置参数:在定义参数时,已经把参数的名字和位置确定了下来,这类位置固定的参数称之为位置参数
def myfunc(s,vt,o):
return "".join((o,vt,s))
print(myfunc("我","喜欢","你"))
#关键字参数,不管顺序,只知道名字即可
print(myfunc(o = "我",s = "你",vt="喜欢"))
# 注:位置参数必须在关键字参数之前****
#默认参数:要把默认参数放到最后****
def myfunc2(z,m,r = "喜欢"):
return "".join((m,r,z))
print(myfunc2("你","我"))
print(myfunc2("变强","我","喜欢")) #覆盖原来的值
print(help(abs)) #abs(x, /)
print(help(sum)) #sum(iterable, /, start=0)
# '/'表示左边的未知数必须是传递位置参数而不能是关键字参数,其右侧都可以
print(abs(-1.5)) #abs 是一个内置函数,用于返回数字的绝对值。
# 注:可以使用‘*’:其左侧可以是任意形式参数,但是其右侧只能死关键字参数才不会出错
def abs(a,b,c):
return (a,b,c)
print(abs(1,b = 2,c = 3))
#收集参数:
# 函数可以返回多个值,python利用元组进行了打包
# print("梦茹","1","2","3")
# ‘*args’用于在函数定义中接收任意数量的位置参数并将它们作为一个元组传递给函数。在这个例子中,*args 允许你传递任意数量的参数给 myfunc 函数。
def myfunc(*args): #通过*可以实现具有打包和解包的能力
print("有{}个参数。".format(len(args)))
print("第2个参数是:{}".format(args[1]))
myfunc("1","2","3")
def myfunc1():
return 1,2,3
print(myfunc1())
# 解包:
x,y,z = myfunc1()
print(x)
def myfunc2(*args):
print(type(args))
myfunc2(1,2,3)
# 注:
def myfunc3(*args,a,b):
print(args,a,b)
myfunc3(1,2,3,4,a = 11,b = 22) #a,b必须为关键字参数
# 收集参数还可以把参数打包成字典:使用'**'
def myfunc4(**kwargs):
print(kwargs)
myfunc4(a = 1,b = 2,c = 3) #{'a': 1, 'b': 2, 'c': 3}
def myfunc5(a,*b,**c):
print(a,b,c)
myfunc5(1,2,3,4,5,6,x = 1,y = 2,z = 3)
# 在形参上使用我们称之为参数的打包,在实参上的使用我们称之为解包参数
#解包:
args = (1,2,3,4)
def myfunc6(a,b,c,d):
print(a,b,c,d)
myfunc6(*args) #*会将元组转换成元素分别赋值给a,b,c,d
kkwargs = {'a':'你','b':'好','c':'呀','d':'ha'}
myfunc6(**kkwargs)
作用域(局部作用域,全局作用域)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~作用域
'''
# 全局变量不易修改
x = 521
def myfunc():
x = 520
print(id(x))
print(x)
print(x) #521
myfunc() #520
print(id(x))
'''
# globals()语句:可以修改全局变量的值
x = 521
def myfunc():
global x
x = 520
print(x)
print(x) #521 全局变量
myfunc() #520 局部变量
print(x) #520 将全局变量的值更改为520
嵌套函数(nonlocal语句)
嵌套函数
def funA():
x = 520
def funB():
x = 521
print("In funB,x = ",x)
funB() #若没有即不可调用funB()
print("In funA,x = ",x)
funA()
nonlocal语句:如果我们非要在内部函数内部去修改外部函数的变量
def funA():
x = 520
def funB():
nonlocal x #在内部函数修改了外部函数作用域的值
x = 521
print("In funB,x = ",x)
funB() #若没有即不可调用funB()
print("In funA,x = ",x)
funA()
LEGB规则
L:locale(作用域) E:Enclised(嵌套函数的外层函数作用域) G:Global(全局作用域) B:Build-In(内置作用域)
不要用str来作为变量名
闭包
例01 引例
1.利用嵌套函数的外层作用域具有记忆能力这个特性
2.将内层函数作为返回值给返回
def funA():
x = 880
def funB():
print(x)
return funB #注意括号的问题,如果加入括号则会显示880
print(funA()) #<function funA.<locals>.funB at 0x00000138ED354B80>(此处显示的是B的引用)
funA()() #880
funny = funA()
funny() #880
def power(exp):
def exp_of(base):
return base ** exp
return exp_of #返回值不要加入“()”
#调用:
square = power(2)
cube = power(3)
print(square(2)) #2的平方
print(cube(2)) #2的三次方
# square(n)表示调用了exp_of函数
def outer():
x = 0
y = 0
def inner(x1,y1):
nonlocal x,y #有记忆的改变x和y的值,内层函数能够记住外层函数作用域
x += x1
y += y1
print(f"现在,x = {x},y = {y}")
return inner
move = outer()
move(1,2) #现在,x = 1,y = 2
move(-1,-2) #现在,x = 0,y = 0
例02 利用闭包函数来实现角色的定向移动
#原点,限制移动范围
origin = (0,0)
x = [-100,100]
y = [-100,100]
def create(post_x=0,post_y=0):
def moving(direction,step):
nonlocal post_x,post_y
#direction表示方向,[0,1]表示向Y轴移动,以此类推
new_x = post_x+direction[0]*step
new_y = post_y+direction[1]*step
#判断是否超出边界
if new_x < x[0]:
post_x = x[0]-(new_x - x[0])
elif new_x > x[1]:
post_x = x[1]-(new_x - x[0])
else:
post_x = new_x
if new_y < y[0]:
post_y = y[0]-(new_y - y[0])
elif new_y > y[1]:
post_y = y[1]-(new_y - y[1])
else:
post_y = new_y
return post_x,post_y
return moving
# 调用
move = create()
print('向右移动20步后,位置是:',move([1,0],20))
print('向右下角移动66步后,位置是:',move([1,-1],66))
装饰器
例01 拿函数当参数,闭包
# 函数调用函数
def myfunc():
print("正在调用myfunc...")
def report(func):
print("主人,我要开始调用函数了...")
func()
print("主人,我调用完函数啦,快夸夸我~")
report(myfunc)
在定义函数时,不要加括号。
在调用函数时,要加括号。
在将函数作为参数传递时,不要加括号。
import time
def time_master(func):
print("开始运行程序...")
stat = time.time()
func()
stop = time.time()
print("结束程序运行...")
print(f"一共耗费了{(stop-stat):.2f}秒。")
def myfunc():
time.sleep(2)
print("Hello My lover.")
time_master(myfunc)
例02 装饰器的写法:语法糖(@time_master更好的易用性、简洁性、可读性和便捷性)
import time
def time_master(func):
def call_func():
print("开始运行程序...")
stat = time.time()
func()
stop = time.time()
print("结束程序运行...")
print(f"一共耗费了{(stop-stat):.2f}秒。")
return call_func
@time_master
def myfunc(): #把myfunc当做一个参数塞进time_master里面,进而调用call_func函数
time.sleep(2)
print("Hello My lover.")
myfunc()
例03 多个装饰器同时用在同一个函数上(注意执行的顺序,从装饰器的编写方式倒这调用)
例04 如何给装饰器传递参数
lambda表达式
例01 # 函数实现方式:匿名函数 内置函数
# lambda表达式
def squareX(x):
return x * x
print(squareX(3))
squareY = lambda y : y * y
print(squareY(3))
print(squareX) #X的引用
print(squareY) #Y的引用
y = [lambda x : x * x,2,3] #y是一个列表
print(y[0](y[1])) #lambda x : x * x是y[0],调用2,得出结果4
print(y[0](y[2]))
例02 lambda表达式只能用于一些简单函数
'''
map() 函数是Python的内置函数,
它接受一个函数和一个或多个可迭代对象(如列表或字符串)作为参数,
并返回一个迭代器,该迭代器将函数应用于可迭代对象的每个元素。
'''
'''
在Python中,ord()函数是一个内置函数,
用于返回单个字符(即一个长度为1的字符串)的Unicode码点,
即该字符在Unicode字符集中的整数表示。
'''
mapped = map(lambda x : ord(x) + 10,"FishC")
print(list(mapped))
# 一般函数
def boring(x):
return ord(x) + 10
print(list(map(boring,"FishC")))
print(list(filter(lambda x : x%2,range(10))))
print(range(10))
'''
filter(lambda x : x % 2, range(10)):
filter()函数接受两个参数:一个函数和一个可迭代对象。
它返回一个新的迭代器,该迭代器包含可迭代对象中使函数返回True值的所有元素。
在这个例子中,filter()将返回range(10)中所有使lambda x : x % 2返回非零值(即True)的元素,
也就是所有的奇数。'''
生成器
例01 generator object:生成器对象
# 生成器(特殊的迭代器,单向,支持next函数) 每调用一次提供一个数据,而列表元组这些可迭代对象则是容器,存放的是已经准备好的所有数据
# 让函数在退出之后还保留状态:闭包,生成器(使用yield代替函数中的return语句即可)
'''
在Python中,counter函数定义了一个生成器(generator)。
生成器是一种特殊的迭代器,它允许你按需生成一系列的值,而不是一次性生成全部的值。
生成器特别适用于需要处理大量数据或需要逐个处理数据的情况,因为它们可以有效地节省内存。
'''
def counter():
i = 0
while i <= 5:
yield i
i += 1
# print(counter()) #<generator object counter at 0x000001EA96A54B80>
for i in counter():
print(i) #0~5
c = counter()
print(c)
print(next(c))
# 迭代器无法使用下标来获取元素的值
例02 利用生成器来实现斐波那契数列
# 利用生成器来实现斐波那契数列 def fib(): back1,back2 = 0,1 while True: yield back1 back1,back2 = back2,back2+back1 f = fib() print(next(f)) print(next(f)) print(next(f)) print(next(f)) print(next(f)) print(next(f)) print(next(f))
例03 生成器表达式
# 生成器表达式 # 注意:里面是一个元组 print((i ** 2 for i in range(10))) #<generator object <genexpr> at 0x0000018F87DFC520> t = ((i ** 2 for i in range(10))) print(next(t)) print(next(t)) print(next(t)) print(next(t)) print() for i in t: print(i)
递归函数(效率比较慢)
例01 递归 函数自我调用的过程(必须要有结束的条件)
# 递归 函数自我调用的过程(必须要有结束的条件) # 注意一下代码的参数 def func(i): if i > 0: print('今天愚人节啊!') i -= 1 func(i) func(5)
例02 汉诺塔
# 汉诺塔
# 递归的应用
def hannoi(n,x,y,z):
if n == 1:
print(x,'-->',z) #如果只有1层,直接将金片从x移动到z
else:
hannoi(n-1,x,z,y) #将x上的n-1个金片移动到y
print(x,'-->',z) #将最底层的金片从x移动到z
hannoi(n-1,y,x,z) #将y上的n-1个金片移动到z
n = int(input('请输入汉诺塔的层数:'))
hannoi(n,'A','B','C')
函数文档、类型注释、内省
例01 函数文档
# 函数文档(最顶端) # help(print()) def exchange(dollar,rate = 6.32): ''' 功能:汇率转换,美元转换成人民币 参数: :param dollar: 美元数量 :param rate: 汇率,默认值是6.32(2022-03-08) :return: 人民币的数量 ''' return dollar * rate print(exchange(20)) help(exchange)
例02 类型注释
# 类型注释
def times(s:str,n:int) -> str: #期待的值是str类型
return s * n
print(times('Zmr',5))
print(times(5,5)) #25
#可以被执行,因为写的类型注释是给人写的机器看不懂
def times(s:list,n:int = 3) -> list:
return s * n
print(times([1,2,3])) #[1, 2, 3, 1, 2, 3, 1, 2, 3]
# 映射类型:字典
def times(s:dict[str,int],n:int = 3) -> list:
return list(s.keys()) * n
print(times({'A':1,'B':2,'C':3}))
例03 内省
# 内省:程序运行的时候能够进行自我检测的一种机制
print(times.__name__) #times
print(times.__annotations__)
# 查看函数文档:
print(exchange.__doc__)
times
{'s': dict[str, int], 'n': <class 'int'>, 'return': <class 'list'>}
功能:汇率转换,美元转换成人民币
参数:
:param dollar: 美元数量
:param rate: 汇率,默认值是6.32(2022-03-08)
:return: 人民币的数量
高阶函数(函数程编程)
例01 functools.reduce
def add(x,y): return x + y import functools print(functools.reduce(add,[1,2,3,4,5])) #15 print(functools.reduce(lambda x,y:x*y,range(1,11))) #3628800
例02 偏函数(partial)
# 偏函数:对指定的函数进行二次包装,将一个函数的多个参数拆分多次进行传递 square = functools.partial(pow,exp=2) print(square(2)) #4 print(square(3)) #9
例03 @wrap
# @wraps装饰器
import time
import functools
def time_master(func):
@functools.wraps(func)
def call_func():
print("开始运行程序...")
stat = time.time()
func()
stop = time.time()
print("结束程序运行...")
print(f"一共耗费了{(stop-stat):.2f}秒。")
return call_func
# @time_master
def myfunc():
time.sleep(2)
print("Hello My lover.")
myfunc = time_master(myfunc)
myfunc()
print(myfunc.__name__)