Python-函数
一、函数定义
初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因变量,y是x的函数。自变量x的取值范围叫做这个函数的定义域
例如y=2*x
函数是逻辑结构化和过程化的一种编程方法。
# python中函数定义方法: def test(x): "The function definitions" x+=1 return x def:定义函数的关键字 test:函数名 ():内可定义形参 "":文档描述(非必要,但是强烈建议为你的函数添加描述信息) x+=1:泛指代码块或程序处理逻辑 return:定义返回值 调用运行:可以带参数也可以不带 函数名()
补充:
1.编程语言中的函数与数学意义的函数是截然不同的俩个概念,编程语言中的函数是通过一个函数名封装好一串用来完成某一特定功能的逻辑,数学定义的函数就是一个等式,等式在传入因变量值x不同会得到一个结果y,这一点与编程语言中类似(也是传入一个参数,得到一个返回值),不同的是数学意义的函数,传入值相同,得到的结果必然相同且没有任何变量的修改(不修改状态),而编程语言中的函数传入的参数相同返回值可不一定相同且可以修改其他的全局变量值(因为一个函数a的执行可能依赖于另外一个函数b的结果,b可能得到不同结果,那即便是你给a传入相同的参数,那么a得到的结果也肯定不同)
2.函数式编程就是:先定义一个数学函数(数学建模),然后按照这个数学模型用编程语言去实现它。至于具体如何实现和这么做的好处,且看后续的函数式编程。
二、为什么要用函数?
1.代码重用
2.保持一致性,易维护
3.可扩展性
三、函数和过程。
过程定义:过程就是简单特殊没有返回值的函数
def test01(): msg='hello The little green frog' print(msg) def test02(): msg='hello WuDaLang' print(msg) return msg t1=test01() t2=test02() print("\n") print ('from test01 return is [%s]' % t1) print ('from test02 return is [%s]' % t2)
总结:当一个函数/过程没有使用return显示的定义返回值时,python解释器会隐式的返回None,
所以在python中即便是过程也可以算作函数。
def test01(): pass def test02(): return 0 def test03(): return 0,10,'hello',['alex','lb'],{'WuDaLang':'lb'} t1=test01() t2=test02() t3=test03() print("\n") print ('from test01 return is [%s]' % type(t1),t1) print ('from test02 return is [%s]' % type(t2),t2) print ('from test03 return is [%s]' % type(t3),t3)
总结:
返回值数=0:返回None
返回值数=1:返回object
返回值数>1:返回tuple
四、函数参数
1.形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
2.实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值
3.位置参数和关键字(标准调用:实参与形参位置一一对应;关键字调用:位置无需固定)
4.默认参数
5.参数组
五、局部变量和全局变量
在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
hobby = "speak English" # 全局变量 def my_hobby(): print("我的爱好",hobby) my_hobby() print(hobby) print("------------") def my_hobby(): hobby = "打豆豆" # 局部变量 print("我的爱好",hobby) my_hobby() # 函数里面的打豆豆 print(hobby) # 还是speak English print("------------") def my_hobby(): global hobby # global 后变成全局变量,作用域所有程序 hobby = "睡觉" print("我的爱好",hobby) my_hobby() print(hobby)
六、前向引用之'函数即变量'
def action(): print("in the action") logger() action() # NameError: name 'logger' is not defined
def logger(): print("in the logger") def action(): print("in the action") logger() action()
def action(): print("in the action") logger() def logger(): print("in the logger") action()
七、嵌套函数和作用域
name = "henry" def change_name(): name = "Henry" def change_name2(): name = "Henry Scofield" print("第3层打印:",name) change_name2() # 调用内层函数 print("第2层打印:",name) change_name() print("最外层打印:",name)
此时,在最外层调用change_name2()会出错,因为:
作用域在定义函数时就已经固定住了,不会随着调用位置的改变而改变。
1 phone='小米' 2 def phone(): 3 phone="苹果" 4 def shouji(): 5 print(phone) 6 return shouji 7 8 p=phone() 9 p()
1 phone='小米' 2 def phone(): 3 phone="苹果" 4 def shouji(): 5 phone="华为" 6 def phone_shouji(): 7 print(phone) 8 return phone_shouji 9 return shouji 10 11 p=phone() 12 p()()
八、递归调用
在函数内部,可以调用其他函数。如果在调用一个函数的过程中直接或间接调用自身本身
1 def calc(n): 2 print(n) 3 if int(n/2) ==0: 4 return n 5 return calc(int(n/2)) 6 7 print(calc(10))
1 import time 2 3 person_list=['Henry','David','Li Hua','Taylor Swift'] 4 def ask_way(person_list): 5 print('-'*60) 6 if len(person_list) == 0: 7 return '没人知道' 8 person = person_list.pop(0) 9 if person == 'Taylor Swift': 10 return '%s说:我知道,体育中心就在天河区那边,下地铁就是' % person 11 print('hi 美男[%s],敢问路在何方' %person) 12 print('%s回答道:我不知道,但念你慧眼识猪,你等着,我帮你问问%s...' %(person,person_list)) 13 time.sleep(3) 14 res=ask_way(person_list) 15 # print('%s问的结果是: %res' %(person,res)) 16 return res 17 18 19 20 res=ask_way(person_list) 21 22 print(res)
递归特性:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
九、匿名函数
不需要显式指定的函数
1 def calc(n): 2 return n**n 3 print(calc(10)) 4 5 #换成匿名函数 6 calc = lambda n:n**n 7 print(calc(10))
1 l=[3,2,100,999,213,1111,31121,333] 2 print(max(l)) 3 4 dic={'k1':10,'k2':100,'k3':30} 5 6 7 print(max(dic)) 8 print(dic[max(dic,key=lambda k:dic[k])])
1 res = map(lambda x:x**2,[1,5,7,4,8]) 2 for i in res: 3 print(i)
十、函数式编程
函数的参数传入,是函数吃进去的食物,而函数return的返回值,是函数拉出来的结果,面向过程的思路就是,把程序的执行当做一串首尾相连的函数,一个函数吃,拉出的东西给另外一个函数吃,另外一个函数吃了再继续拉给下一个函数吃。。。
例如:
用户登录流程:前端接收处理用户请求-》将用户信息传给逻辑层,逻辑词处理用户信息-》将用户信息写入数据库
验证用户登录流程:数据库查询/处理用户信息-》交给逻辑层,逻辑层处理用户信息-》用户信息交给前端,前端显示用户信息
高阶函数:
满足俩个特性任意一个即为高阶函数
1.函数的传入参数是一个函数名
2.函数的返回值是一个函数名
map函数
1 array=[1,3,4,71,2] 2 3 ret=[] 4 for i in array: 5 ret.append(i**2) 6 print(ret)
1 #如果我们有一万个列表,那么你只能把上面的逻辑定义成函数 2 def map_test(array): 3 ret=[] 4 for i in array: 5 ret.append(i**2) 6 return ret 7 8 print(map_test(array))
1 #如果我们的需求变了,不是把列表中每个元素都平方,还有加1,减一,那么可以这样 2 def add_num(x): 3 return x+1 4 def map_test(func,array): 5 ret=[] 6 for i in array: 7 ret.append(func(i)) 8 return ret 9 10 print(map_test(add_num,array))
1 #可以使用匿名函数 2 print(map_test(lambda x:x-1,array))
1 #上面就是map函数的功能,map得到的结果是可迭代对象 2 print(map(lambda x:x-1,range(5)))
reduce函数
1 from functools import reduce 2 #合并,得一个合并的结果 3 array_test=[1,2,3,4,5,6,7] 4 array=range(100) 5 6 #可以从列表左边弹出第一个值 7 def reduce_test(func,array): 8 l=list(array) 9 res=l.pop(0) # res=0,删掉了0 10 for i in l: # i是1-99 11 res=func(res,i) 12 return res 13 14 print(reduce_test(lambda x,y:x+y,array))
1 def reduce_test(func,array,init=None): 2 l=list(array) 3 if init is None: 4 res=l.pop(0) 5 else: 6 res=init 7 for i in l: 8 res=func(res,i) 9 return res 10 11 print(reduce_test(lambda x,y:x+y,array)) 12 print(reduce_test(lambda x,y:x+y,array,50))
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理