函数:在编写程序的过程中,有某一功能代码块出现多次, 但是为了提高编写的效率以及代码的重用,所以把具有独立功能的代码块组织为一个小模块,这就是函数
Python中的函数是一组被命名的可执行代码,用于完成特定的任务。函数可以接收输入参数,执行相应的处理,然后返回结果。在编程中,函数的概念源自于数学的函数,但编程中的函数更加广泛,主要用于提高代码的复用性和可维护性。
一、函数
(一)函数的用途和好处
- 提高代码复用性:通过定义函数,可以将重复的代码块封装起来,避免重复编写相同的代码。
- 提高代码可读性:通过函数命名和参数,使得代码更加清晰易懂。
- 便于维护:当需要修改功能时,只需修改函数内部的代码,而不需要修改调用该函数的每一处代码
(二)函数定义
在Python中,使用关键字def
来定义一个函数。函数的定义包括函数名称、参数列表和函数体
def + 关键字 + 小括号 + 冒号+ 换行缩进 + 代码块 定义一个函数
def 函数名(): 代码块
def my_function(param1, param2):
# 函数体
return result
(三)函数调用
函数名加()即可调用该函数
result = my_function(value1, value2)
# 函数的定义
# def 函数名(参数列表):0-n 个
# 代码块
def say_hello():print("Hello,Python!")#函数的调用
say_hello()
say_hello()
say_hello() # 多次调用
(四)函数的参数类型
Python中的函数参数类型包括:
-
位置参数(Positional Argument):这是最常见的参数类型,调用函数时,实参变量的顺序必须与形参变量的顺序一致。例如,定义一个函数
user_info(name, age, gender)
,调用时必须按照user_info('Tom', 20, 'male')
的顺序传递参数 -
关键字参数(Keyword Argument):关键字参数允许在函数调用时使用参数名来指定参数的值,不需要按照参数的顺序。例如,
user_info(name='Tom', age=20, gender='male')
-
缺省参数(Default Argument):缺省参数在函数定义时提供一个默认值,调用函数时如果不提供该参数的值,则使用默认值。例如,
def add(a, b=5, c=10): return a + b + c
,调用时可以省略b
和c
3。 -
不定长参数(Variable-length Parameters):用于不确定调用时会传递多少个参数的场景。分为包裹位置参数(*args)和包裹关键字参数(**kwargs)。例如,
def f1(*args, **‌kwargs): print(args, kwargs)
,可以接收任意数量的位置和关键字参数
'''
函数的定义
def 函数名(参数列表):0-n 个代码块
'''
def say_hello():print("Hello,Python!")#函数的调用
say_hello()
say_hello()
say_hello() # 多次调用print('--------函数参数--------')
'''
参数的分类:
位置参数(必选参数)、缺省参数[默认参数]、可选参数、关键字参数
参数:其实就是函数为了实现某项特定的功能,进而为了得到实现功能所需要的数据
'''
# 1、位置参数(必选参数)
# 形式参数:只是意义上的一种参数,在定义的时候是不占内存地址的
def sum(a,b):sum=a+bprint(sum)pass
# 函数调用 在调用的时候必选参数 是必须要赋值的
#10,5是实际参数;实际参数:实参,实实在在的参数,是实际占用内存地址的
print('位置必选参数:%d',sum(10,5))
# 如下写法报错:TypeError: sum() missing 1 required positional argument: 'b'
# sum(5)# 2、默认参数【缺省参数】 始终存在于参数列表中的尾部
def sum1(a,b=20):print('缺省参数使用=%d'%(a+b))pass#在调用的时候如果未赋值,就会用定义函数时给定的默认值;如果赋值了则使用实参值替代
sum1(10)def sum2(a,b=20,c=30):print('缺省参数使用=%d'%(a+b+c))pass
sum2(10,5)'''
3、可变参数(当参数的个数不确定时使用,比较灵活)
可变参数(args): 使用一个星号()前缀 (*args)
可变参数允许函数接收任意数量的位置参数,这些参数在函数内部自动组装成一个元组(tuple)
'''
def getComputer(*args):'''
# 计算累加和
# :param args: 可变长的参数类型
# :return:
# '''# print(args)result=0for item in args:result+=itempassprint('可变参数result=%d'%result)passgetComputer(1)
getComputer(1,2)
getComputer(1,2,3)
getComputer(1,2,3,4,5,6,7,8)'''
关键字可变参数:0-n
使用 ** 来定义
关键字可变参数(*kwargs): 使用两个星号()前缀 (**kwargs),
关键字可变参数允许函数接收任意数量的关键字参数,这些参数在函数内部自动组装成一个字典(dict)
在函数体内,参数关键字是一个字典类型,key是一个字符串
'''
def keyFunc(**kwargs):print('关键字可变参数:',kwargs)pass# 不可以传递的,报错:TypeError: keyFunc() takes 0 positional arguments but 3 were given
# keyFunc(1,2,3)
dictA={"name":'小明',"age":18}
keyFunc(**dictA)
keyFunc(name='小黑',age=20,)
keyFunc()'''
可变参数和关键字可变参数组合使用
可变参数和关键字可变参数可以同时使用,但是它们的顺序必须是:先定义位置参数和关键字参数,然后是一个星号后跟一个双星号
def my_function(pos_arg, *args, **kwargs):
'''
def complexFunc(*args,**kwargs):print('组合可变参数,关键字可变参数:',args)print('组合可变参数,关键字可变参数:',kwargs)pass
complexFunc(1,2,name='张晓明')
complexFunc(age=36)# 报错:SyntaxError: arguments cannot follow var-keyword argument
# def testMap(**kwargs,*args):
# '''
# 可选参数必须放到关键字可选参数之前
# 可选参数:接受的数据是一个元组类型
# 关键字可选参数:接受的数据是一个字段类型
# :param kwargs:
# :param args:
# :return:
# '''
# pass'''
函数返回值
概念:函数执行完以后会返回一个对象,如果在函数的内部有return 就可以返回实际的值,否则返回None
类型:可以返回任意类型,返回值类型应该取决于return后面的类型
用途:给调用方返回数据
在一个函数体内可以出现多个return值:但是肯定只能返回一个return
如果在一个函数体内 执行了return,意味着函数就执行完成退出了,return后面的代码语句将不会执行
'''
def Sum(a,b):sum=a+breturn sum#将计算的结果返回passresult=Sum(10,5) #将返回值赋给其他的变量
print('函数返回值%d'%result) #函数的返回值返回到调用的地方def calComputer(num):li=[]result=0i=1while i<=num:result+=ii+=1passli.append(result)return lipassvalue=calComputer(10)
print(type(value)) #value 类型
print('函数返回值',value)
def returnTuple():'''返回元组类型的数据:return:'''# return 1,2,3return {"name":"张晓明"}passA=returnTuple()
print(type(A))'''
函数嵌套
函数可以嵌套调用,即在一个函数内部调用另外一个函数。 内层函数可以访问外层函数中定义的变量,但不能重新赋值(rebind)
'''
def fun1():print("--------------fun1 start-------------------")print("--------------执行fun1代码省略-------------------")print("--------------fun1 end-------------------")passdef fun2():print("--------------fun2 start-------------------")# 调用第一个函数fun1()print("--------------fun2 end-------------------")passfun2()
输出:
Hello,Python!
Hello,Python!
Hello,Python!
--------函数参数--------
15
位置必选参数:%d None
缺省参数使用=30
缺省参数使用=45
可变参数result=1
可变参数result=3
可变参数result=6
可变参数result=36
关键字可变参数: {'name': '小明', 'age': 18}
关键字可变参数: {'name': '小黑', 'age': 20}
关键字可变参数: {}
组合可变参数,关键字可变参数: (1, 2)
组合可变参数,关键字可变参数: {'name': '张晓明'}
组合可变参数,关键字可变参数: ()
组合可变参数,关键字可变参数: {'age': 36}
函数返回值15
<class 'list'>
函数返回值 [55]
<class 'dict'>
--------------fun2 start-------------------
--------------fun1 start-------------------
--------------执行fun1代码省略-------------------
--------------fun1 end-------------------
--------------fun2 end-------------------
注:
1、可变参数(args): 使用一个星号()前缀 (*args) 可变参数允许函数接收任意数量的位置参数,这些参数在函数内部自动组装成一个元组(tuple)
2、关键字可变参数(*kwargs): 使用两个星号()前缀 (**kwargs), 关键字可变参数允许函数接收任意数量的关键字参数,这些参数在函数内部自动组装成一个字典(dict)
3、可变参数和关键字可变参数可以同时使用,但是它们的顺序必须是:先定义位置参数和关键字参数,然后是一个星号后跟一个双星号
def my_function(pos_arg, *args, **kwargs):
(五)函数的返回值
在Python中,函数可以返回一个值。使用return
语句可以从函数中返回值。函数执行到return
语句时将停止执行,并将return
后面的值作为函数的结果返回。如果函数没有return
语句,或者return
语句不跟任何值,那么函数将返回None
'''
函数返回值
概念:函数执行完以后会返回一个对象,如果在函数的内部有return 就可以返回实际的值,否则返回None
类型:可以返回任意类型,返回值类型应该取决于return后面的类型
用途:给调用方返回数据
在一个函数体内可以出现多个return值:但是肯定只能返回一个return
如果在一个函数体内 执行了return,意味着函数就执行完成退出了,return后面的代码语句将不会执行
'''
def Sum(a,b):sum=a+breturn sum#将计算的结果返回passresult=Sum(10,5) #将返回值赋给其他的变量
print('函数返回值%d'%result) #函数的返回值返回到调用的地方def calComputer(num):li=[]result=0i=1while i<=num:result+=ii+=1passli.append(result)return lipassvalue=calComputer(10)
print(type(value)) #value 类型
print('函数返回值',value)
def returnTuple():'''返回元组类型的数据:return:'''# return 1,2,3return {"name":"张晓明"}passA=returnTuple()
print(type(A))
(六)嵌套函数
函数可以嵌套调用,即在一个函数内部调用另外一个函数。 内层函数可以访问外层函数中定义的变量,但不能重新赋值(rebind)
'''
函数嵌套
函数可以嵌套调用,即在一个函数内部调用另外一个函数。 内层函数可以访问外层函数中定义的变量,但不能重新赋值(rebind)
'''
def fun1():print("--------------fun1 start-------------------")print("--------------执行fun1代码省略-------------------")print("--------------fun1 end-------------------")passdef fun2():print("--------------fun2 start-------------------")# 调用第一个函数fun1()print("--------------fun2 end-------------------")passfun2()
(七)函数4种基本类型
1、无参数,无返回值,一般用于提示信息打印
2、无参数,有返回值,多用在数据采集中,比如获取系统信息
3、有参数,无返回值,多用在设置某些不需要返回值的参数设置
4、有参数,有返回值,一般是计算型的,需要参数,最终也要返回结果
# 无参数,无返回值
def myprint(): print("-" * 20)# 无参数,有返回值
def mycpu():# 获取cpu信息return info# 有参数,无返回值
def set(a):pass# 有参数,有返回值
def cal(a, b):c = a + b
(八)pass
语句
在Python中,pass
语句是一个空操作语句,主要用于保持程序结构的完整性,并不执行任何操作。 它常用于以下几种情况:
-
占位符:当你在代码中预留一个位置,计划将来添加功能时,可以使用
pass
作为占位符。例如,在定义一个类的方法时,如果暂时不想实现具体功能,可以使用pass
。class Student: def __init__(self, name, age): self.name = name self.age = age def display_info(self): pass # 将来添加显示信息的功能 def update_info(self, new_name, new_age): pass # 将来添加更新信息的功能
-
强制缩进:在某些情况下,为了保持代码块的正确缩进,可能需要一个空语句。此时,可以使用
pass
。 -
避免语法错误:如果你需要一个语句块但不想执行任何操作,可以使用
pass
来避免语法错误。这在编写框架或测试代码时尤为有用。def my_empty_function(): pass # 此函数暂时没有实现内容
需要注意的是,虽然pass
语句在开发过程中可以作为临时占位符,但在最终代码中应尽量避免使用,以免影响代码的可读性和执行效率。此外,pass
语句不能替代continue
和break
语句,后者用于控制循环的执行流程
二、局部变量和全局变量
(一)局部变量和全局变量
在Python中,全局变量和局部变量的主要区别在于它们的作用域、生命周期和访问方式
-
作用域:
- 全局变量:在程序的全局范围内可见,可以在任何函数中访问和修改。
- 局部变量:仅在定义它的函数内部可见,外部函数无法访问。
-
生命周期:
- 全局变量:从定义开始到程序结束始终存在于内存中。
- 局部变量:仅在函数执行期间存在,函数执行结束后,局部变量被销毁。
-
访问方式:
- 全局变量:可以在任何函数内部直接访问和修改,但如果在函数内部修改全局变量的值,需要使用
global
关键字进行声明。 - 局部变量:只能在定义它的函数内部访问和修改。
- 全局变量:可以在任何函数内部直接访问和修改,但如果在函数内部修改全局变量的值,需要使用
-
冲突风险:
- 全局变量:由于多个函数可以同时访问和修改,存在冲突风险,可能导致命名冲突或不可预测的行为。
- 局部变量:由于其作用域限制,不会与其他函数的局部变量发生冲突
'''
局部变量:在函数内部定义的变量【作用域仅仅局限在函数的内部】
不同的函数,可以定义相同的局部变量,但是各自用各自的 不会产生影响
局部变量的作用:为了临时的保存数据 需要在函数中定义来进行存储全局变量:
当全局变量和局部变量出现重复定义的时候,程序会优先执行使用函数内部定义的变量
如果在函数的内部要想对全局变量进行修改的话,对于不可变类型【str 元组 number】必须使用global 关键字进行声明对于可变类型【dict、list】,全局变量要想在函数中修改的话,不需要用global关键字去声明
因为对象的内存地址不会改变
'''# 以下两个是全部变量
profession='计算机信息'
name='张晓明'
def printInfo():name='张二明' #局部变量print('姓名:{},专业:{}'.format(name,profession))pass
def printInfo2():name='张三明'print(name,profession)pass
def changeGlobal():'''要修改全局变量:return:'''global profession #声明全局变量 后才可以修改profession='金融' #局部变量passchangeGlobal()
print(profession)
printInfo2()
printInfo()print('--------可变类型')
# 针对数据类型来讲 可变类型和不可变类型
# 可变类型 dict list;引用地址未变
li=[1,2]
print(id(li))
li.append('Python语言')
print(li)
print(id(li))print('--------不可变类型')
# 不可变类型 str tuple number【int、float、complex】
age=18
print(id(age))
age=20
print(id(age))
age1=age
print('直接赋值',id(age))
age1=15
print(id(age1))
name='张晓明'
print(id(name))
name='张二明'
print(id(name))print('--------可变类型修改全局变量--------')
listObj=[] #全局变量
def demoList():listObj.append('你好')passprint(id(listObj))
demoList()
print(listObj)
print(id(listObj))
输出:
金融
张三明 金融
姓名:张二明,专业:金融
--------可变类型
2114739546944
[1, 2, 'Python语言']
2114739546944
--------不可变类型
140719003919816
140719003919880
直接赋值 140719003919880
140719003919720
2114739573568
2114739572768
--------可变类型修改全局变量--------
2114739543744
['你好']
2114739543744
(二)引用
在Python中,引用是指向内存空间中的对象的指针。当创建一个变量时,Python会分配一段内存空间来存储这个变量所代表的值,然后将这个变量名与该内存空间中的地址关联起来,这样就建立了一个引用。当你使用该变量时,实际上是通过该引用来访问这个内存空间中的对象,从而对其进行操作。
通俗来说,引用是指一个变量或者对象对于另一个对象的指向关系,类似于指针,变量指向的是内存地址
在python中,值是靠引用来传递来的,可以用id()函数查看一个对象的引用是否相同,id是值保存在内存中那块内存地址的标识。
在Python中,变量实际上是一个对象的名称,它指向存储在内存中的对象。例如,在下面这个例子中,变量a
指向了一个整数对象2
:
a = 2
在这个例子中,等号=
符号实际上是赋值操作符,它将整数对象2
赋值给了变量a
。因此,变量a
实际上是一个指向整数对象2
的引用
#不可变类型
a=1
def func(x):print('x的地址:{}'.format(id(x)))x=2print('x的值修改之后地址:{}'.format(id(x)))print(x)passprint('a的地址:{}'.format(id(a)))
func(a)
print(a)print('---------可变类型--------')
# 可变类型
li=[]
def testRenc(parms):li.append([1,2,3,6,8])print('调用前地址:',id(parms))print('内部的{}'.format(parms))passprint('调用前地址:',id(li))
testRenc(li)
print('外部的变量对象{}'.format(li))
print('调用后地址:',id(li))# 注:在python当中 万物皆对象,在函数调用的时候,实参传递的就是对象的引用
输出:
a的地址:140718885233576
x的地址:140718885233576
x的值修改之后地址:140718885233608
2
1
---------可变类型--------
调用前地址: 2503471655936
调用前地址: 2503471655936
内部的[[1, 2, 3, 6, 8]]
外部的变量对象[[1, 2, 3, 6, 8]]
调用后地址: 2503471655936
三、匿名函数和递归函数
(一)匿名函数
在Python中,匿名函数通常使用lambda关键字定义。lambda函数是一种小型函数,它可以接受任意数量的参数,但只能有一个表达式。它通常用于简单的、不需要明确命名的函数
lambda 参数1,参数2,参数3: 执行代码语句
# 定义一个匿名函数,接受两个参数并返回它们的乘积
multiply = lambda x, y: x * yresult = multiply(5, 6)
print(result) # 输出: 30
'''
匿名函数
语法:
lambda 参数1,参数2,参数3,...:表达式
特点
1、使用lambda关键字去创建函数
2、没有名字的函数
3、匿名函数冒号后面的表达式有且只有一个, 注:是表达式,而不是语句
4、匿名函数自带return,而这个return的结果就是表达式计算后的结果
缺点
lambde只能是单个表达式,不是一个代码块,lambde的设计就是为了满足简单函数的场景,
仅仅能封装有限的逻辑,复杂逻辑实现不了,必须使用def来处理
'''
def computer(x,y):'''计算数据和:param x::param y::return:'''return x+ypass
# 对应的匿名函数
M=lambda x,y:x+y
# 通过变量去调用匿名函数
print(M(3,5))
print(computer(2,4))result=lambda a,b,c:a*b*c
print(result(4,3,2))age=int(input('请输入年龄:'))
print('可以上学' if age>18 else '继续上学') #可以替换传统双分支的写法funcTest=lambda x,y:x if x>y else y
print(funcTest(2,12))rs=(lambda x,y:x if x>y else y)(6,2) #直接的调用
print(rs)
varRs=lambda x:(x**2)+10
print(varRs(10))
#
(二)递归函数
Python中的递归函数,这是一种函数直接或间接调用自身的方法。在使用递归时,必须有一个明确的退出条件(基准情况),否则递归将无限进行下去,最终导致栈溢出错误
# 定义一个递归函数,用于计算阶乘
def factorial(n):if n == 0: # 基准情况return 1else:return n * factorial(n - 1) # 递归调用result = factorial(5)
print(result) # 输出: 120
'''
递归满足的条件
函数调用自己本身,必须有一个明确的结束条件
优点:逻辑简单、定义简单
缺点:容易导致栈溢出,内存资源紧张,甚至内存泄漏
'''# 求阶乘
# 循环的方式去实现
def jiecheng(n):result=1for item in range(1,n+1):result*=itempassreturn resultprint('10的阶乘{}'.format(jiecheng(10)))# 递归方式去实现
def diguiJc(n):'''递归实现:param n: 阶乘参数:return:'''if n==1:return 1else:return n*diguiJc(n-1)pass# 递归调用
print('5的阶乘{}'.format(diguiJc(5)))# 递归案例,树形结构的遍历
import os #引入文件操作模块
def findFile(file_Path):listRs=os.listdir(file_Path) #得到该路径下所有文件夹for fileItem in listRs:full_path=os.path.join(file_Path,fileItem) #获取完整的文件路径if os.path.isdir(full_path):#判断是否是文件夹findFile(full_path) #如果是一个文件夹 再次去递归else:print(fileItem)passpasselse:returnpass# 调用搜索文件夹对象
findFile('E:\\软件')