前言:
使用函数可以解决代码重复使用率,以及增加代码可读性。对部分代码划分进行统一管理。可以将一些代码集合成一个功能对应一个函数,当功能需要拓展时,可以很方便就能找到对应的函数进行添加代码。
Python有许多内置函数,如print()。当然也可以自定义函数。
目录
自定义函数
你可以自定义一个自己想实现功能的函数,定义函数的规则:
- 1、def 关键字起始
- 2、函数名后面跟括号
- 3、最后冒号结尾
- 4、参数(前3个是函数定义必备,参数根据情况而定)
- 5、返回值(前3个是函数定义必备,返回值根据情况而定)
函数:先定义
、后调用
基本语法:
# 函数标准写法
def 函数名():
函数体代码
# 有参数时的写法
def 函数名(参数):
函数体代码
实例:
让我们用函数输出一段字符
def fun():
print('this is my first fun')
fun() # 直接通过函数名来调用定义的函数
执行后结果:'this is my first fun'
python优先检测语法错误,如果函数里面有语法错误会直接报错,那么如果是逻辑错误的话,没有调用这个函数就不会产生报错信息,实例:
python对语法格外严格,只要出现语法错误那么所有代码全部不能运行
def fun():
print('123' # 少了一个括号,这是为语法错误,所以整体代码都不会运行
报错信息:SyntaxError: invalid syntax
def bar():
page
# 这是表示在找page这个变量,未找到产生逻辑错误,没有调用这个函数就不会报错信息
无报错信息:未调用就不会执行里面的代码,所以不会产生报错信息
bar()
调用后产生报错信息:NameError: name 'page' is not defined
没有page 这个变量
函数传参
可以把我们在外面定义好的内容,传递给函数帮我们执行相关操作
函数括号里面的内容就是参数
参数可分为:形参和实参
def fun(x): # 形参(固定的参数,可以有不同的值传递进来)
pass # 表示占位的意思,防止代码报错,没有其它效果
fun(10) # 实参(不固定参数,可以是变量)
# 这种形参可以称为位置形参:表示从左至由定义的形参
def fun(x,y):
# x接收到实参的一个值 x=10
# y接收到实参的而个值 y=20
pass
# 这种实参可以称为位置实参:表示从左至右依次传入值
fun(10,20)
def func(x,y):
pass
# 向函数传递一个实参,但是函数定义了两个形参,那么这样会产生报错,
func(10)
所以,函数有多少个形参,那么调用时就要传递多少个实参
注意:传递的实参位置要和形参定义的位置相同,才能把对应的值给到它们
实例:参数的传入
# 定义参数名(和变量名是相差无几的)
def fun(x,y): # 表示函数接收外界传递两个参数
'''
x拿到调用fun函数 里面填的第一个实参
y拿到调用fun函数 里面填的第二个实参
'''
x += y # 对传递进来的参数进行操作
print(x)
fun(10,20) # 将10传递给 x形参,将20传递给 y形参
执行完结果为:30
a = 40
b = 50
fun(a,b) # 将变量a和变量b的值传递进去
执行完结果为:90
注意:如果函数定义了两个形参,那么传递实参数就必须是两个
如:fun(60) 这种就会报错
默认参数
可以直接对形参设置默认参数,没有传递参数的话,可以使用默认的参数,使用默认参数可以不用向那个位置的形参传递参数,但是如果有传递进来的参数会覆盖默认形参
# 表示设置了一个默认值的形参
def info(name,age,gender='male'):
print(name,age,gender)
# 可以不向那个形参传递参数,因为参数,这里多个用户都是使用默认的,所以不用传递
info('张三',18)
info('李四',25)
info('王五',23,gender='female') # 有不同的再传递即可,覆盖默认形参
打印结果:
张三 18 male
李四 25 male
王五 23 female
注意:使用位置形参和默认形参的位置
# 正确写法:位置形参 在 默认形参前面
def info(name,gender='male'):
pass
# 错误写法:默认形参 在 位置形参前面
def info(gender='male',name): # 直接语法错误,不允许这样写法
pass
关键字实参
传递实参时,可以通过形参名来对应到它,不需要对应顺序来传值
def info(name,age):
print('he/she name is %s ' % name)
print('he/she age is %s ' % age)
info(age=18,name='tom') # 通过关键字传入参数可以不需要对应顺序
打印结果:
'he/she name is tom'
'he/she age is 18'
不定长参数
函数不确定实参传递的内容个数,那么就可以使用特定的形参来接收实参不定长内容
形参不定长
通过* 接收实参,将实参溢出的内容
以元组(tuptle) 的形式导入,不能接受关键字传入
# 可以有两种写法:
第一种:只确定第一个参数
# 在形参中带*:*会将溢出位置实参汇总成元组,然后赋值给其后变量名,通常应该是args
def info(name,*args):
print(name) # 获取到实参的第一参数 ‘tom'
print(args) # 溢出的所有实参都会在args里面 (4,5,6,7)
info('tom',4,5,6,7)
打印结果:
'tom'
(4,5,6,7)
第二种:完全不确定参数
def info(*args):
for i in args: # 将实参传递的全部内容打印出来
print(i)
info('tom',4,5,6,7)
打印结果:('tom',4,5,6,7)
练习:计算传入值的总和
def my_sum(*args): # 直接接收所有传递进来的实参
sum = 0
for i in args: # args:(1,2,3,4,5,6,7)
sum += i # 每次拿到里面的值赋给自身
return sum
res = my_sum(1,2,3,4,5,6,7) # 传递多个数字进去
print(res)
打印结果:28
通过** 接收实参,注意:只接受关键字实参传入
def info(**kwargs): # 接收关键字的实参让后将它们关键字作为key 值作为values
print('name is %s ' % kwargs['name'])
print('age is %s ' % kwargs['age'])
print('gender is %s ' % kwargs['gender'])
print('height is %s ' % kwargs['height'])
# 因为函数里面定义一个字典模式接收内容,传递必须为关键字实参
info(name='tom',height=185,gender='male',age=18)
打印结果:
name is tom
age is 18
gender is male
height is 185
结合*与**一起使用
def info(*args,**kwargs): # args('年份',2020,'月份',11)
for i in args: # kwargs = {'name':'tom'.....}
print(i)
for k,v in kwargs.items():
print(k,v)
info('年份:',2020,'月份',11,name='tom',height=185,gender='male',age=18)
实参不定长
在实参带*:会将紧跟其后的实参打撒成位置实参,注意后跟的应该是一个可以被for循环循环的类型
def func(a,b,c,d):
print(a,b,c,d)
func(*"hell") # func("h","e","l","l")
func(*[11,22,33,44]) # func(11,22,33,44)
func(11,22,*[33,44]) # func(11,22,33,44)
func(11,22,*{"k1":333,"k2":4444}) # func(11,22,"k1","k2")
在实参带**: ** 会将紧跟其后的实参打撒成关键字实参,注意**后跟的必须是一个字典
def func(a,b,c,d):
print(a,b,c,d)
func(**{"k1":111,"k2":222}) # func(k1=111,k2=222)
func(**{"a":1111,"b":22,"c":33,"d":44}) # func(a=11,c=22,b=44,d=33)
#func(**[("a",111),("b",111),("c",111),("d",111)]) 错误,不是字典
传入不可变数据类型
无法改变外部内容,因为传递进来的数据类型为不可变
def fun(x):
print(id(x)) # 查看传递进来的内存地址
4498836416
x = 1 # 改变了形参的内容,这里开始往下 x这个形参内容都为1
print(id(x))
4498836128 # 内存地址变动
res = 10
print(id(res)) # 查看它的内存地址
4498836416
fun(res) # 将这个变量传递进去
传递可变数据类型
传递进来的参数,内存地址和原值是一样的,但数据类型为可变的话,就可以通过改变形参,间接达到修改原值的效果,实例:
def fun(x):
print("函数内取值前:%s" % x)
[1,2,3,4]
x.append([7,8,9]) # 修改传入的列表
print("函数修改形参后:%s" % x)
[1,2,3,4,[7,8,9]]
return
res = [1,2,3,4]
fun(res) # 将列表传递进去
print("函数外取值:%s" % res)
[1,2,3,4,[7,8,9]] # 可以发现,原值被修改
函数返回值
通过return这个关键字,返回一个结果,或者退出这个函数
实例1:return的使用方法
def fun(x,y):
if x > y:
# 如果传递进来的参数 x大于y 那么就把x的值返回给使用这个函数的代码
return x
else:
return y # 否则返回y
# fun(10,20) 这样可以得到返回返回值,但是要用于一个变量来接收保存
res = fun(10,20) # 定义变量来接收函数返回的值
print(res)
打印结果:20
实例2:测试return 后的效果
def test_rt(values):
sums = 0
for i in values: # 遍历传递进来的参数
sums += 1 # 没遍历到一个元素都加1
return sums # 返回值
# return 以下代码全部不会执行,因为使用return以后函数就已经结束了
print(sums)
test_rt('测试return以后的效果')
# 没有任何效果
def test_rt():
print('测试return后面不跟结果')
return
res = test_rt()
print(res) # 得到一个None(空)值
实例3:写一个统计元素个数的函数,类似于len方法
def count(values):
sum = 0
for i in values: # 遍历传递进来的参数
sum += 1 # 没遍历到一个元素都加1
return sum # 返回获取到的元素个数
lis = [1,2,3,4,5]
lis_count = count(lis) # 将列表传递进去
print(lis_count)
结果为:5
print(count('GoodMorning'))
结果为:11
函数的执行顺序
当我在下面调用fun函数后,流程就是把fun函数里面的代码拿到那个位置执行,那么在下面执行代码的时候,bar已经定义好了,所以正常运行
实例1
def fun():
print('this is fun')
bar() # 调用bar函数
def bar():
print('this is bar')
fun()
'''
print('this is fun')
bar() # 拿到这里运行的时候,bar函数就已经定义了
'''
实例2
再次观察,换一种写法
def fun():
print('this is fun')
bar() # 调用bar函数
fun()
'''
print('this is fun')
bar() # 观察,这里是否能找到bar函数?
'''
产生报错:NameError: name 'bar' is not defined # 没有找到bar
def bar():
print('this is bar')
'结果是未找到,因为bar函数在下面才定义,上面是无法调用到的'
增加函数的描述
对函数接收的参数进行一个描述:说明需要接收的是什么类型,不同于往常的注释
'''
告调用者,需要传递什么类型的参数进来
实际并没有什么作用上的效果,只是在阅读的时候起到作用
'''
# 告诉调用者,需要传递两个int类型的值
def sums(x:int, y:int) -> int: # 告诉调用者,返回的变量类型
return x + y
res = sums(10,20) # 得到一个返回结果
打印结果:30
# 即使传入字符串也不会有任何问题,因为上面增加是描述本身就没有什么效果。
res = sums('xx','yy')
打印结果:xxyy
至此,可以使用函数集合代码成为一个功能,并进行调用,根据自己需求对函数进行基本操作。
函数未完待续:
函数对象:https://blog.csdn.net/m0_46958731/article/details/110220132
函数嵌套:https://blog.csdn.net/m0_46958731/article/details/110223695
技术小白记录学习过程,有错误或不解的地方请指出,如果这篇文章对你有所帮助请
点赞 收藏+关注
谢谢支持!