函数就是实现某一特定功能的代码的封装
(函数就是把实现某一个功能的代码打成一个包,以后再需要这段代码对应的功能的时候不需要再写这
段代码,而是直接调用封装这段代码的函数)
(1)系统函数(别人造好机器):python自带的函数,例如print、input、type、max、min、sorted等
(2)自定义函数(自己造的机器):由程序员自己创建的函数
def 函数名(形参列表):
函数说明文档
函数体
(1)def :关键字;固定写法
(2)函数名 :由程序员自己命名,但是必须符合命名要求和规范
要求:是标识符;不是关键字
规范:见名知义(看到函数名就大概知道这个函数对应的功能是什么)
字母都小写,多个单词用下划线隔开
不使用系统的函数名、类名、模块名
(3)(): :固定写法
(4)形参列表:以’变量名1, 变量名2, 变量名3, …'的形式存在,这儿的变量名可以有也可以没有
形参的作用:将函数外部的数据传递到函数里面
怎么确定形参:看实现函数的功能需不需要额外的数据,需要几个(在函数体中就把 形参当成对应的数据使用)
(5)函数说明文档:本质就是一个多行注释,用来描述函数的功能和使用方法
(6)函数体:结构上:和def保持一个缩进的一条或者多条语句(至少一条)
逻辑上:函数体就是实现函数功能的代码
RIGHT Example:
def sum2(num1, num2):
"""
求两个数的和(函数功能说明区)
:param num1:第一个数(参数说明区)
:param num2:第二个数
:return:None(返回值说明)
"""
print(num1 + num2)
APPLICATION 1 定义一个函数,统计指定字符串中中文的个数:
def count_chinese(str1):
"""
统计字符串中中文的个数
:param str1: 指定的字符串
:return:None
"""
count1 = 0
for x in str1:
if '一' <= x <= '龥':
count1 += 1
print(count1)
count_chinese('薛喵喵123afg') # 3
APPLICATION 2 定义一个函数,将指定的数据插入到指定列表的最前面:
def prepend(list2, target):
"""
将指定数据插入到指定列表最前面
:param list2: 指定列表
:param target:指定数据
:return:
"""
list2.insert(0, target)
print(list2)
prepend([1, 2, 3, 4], 5) # [5, 1, 2, 3, 4]
APPLICATION 3 定义一个函数,求任意一个整数的阶乘:
def factorial(num3):
"""
求任意正整数的阶乘
:param num3:需要求阶乘的整数
:return:None
"""
product = 1
for x in range(1, num3 + 1):
product *= x
print(product)
factorial(4) # 24
APPLICATION 4 定义一个函数,求任意一个圆的面积:
def area_circle(r):
"""
求任意正整数的阶乘
:param num3:需要求阶乘的整数
:return:None
"""
print(3.14 * r ** 2)
area_circle(2) # 12.56
注意:定义函数不会执行函数体,调用函数才会执行函数体
RIGHT Example:
def func1():
print('hello world!') # 无打印结果
print('abc'[10]) # 无打印结果,也不报错
函数名(实参列表)
(1)函数名 :需要哪个函数的功能就调用哪个函数,就写哪个函数的函数名
(注意:函数名必须是已经定义好的函数的函数名)
(2)() :固定写法
(3)实参列表:以’数据1, 数据2, 数据3, …'的形式存在
实参就是通过形参从函数外部传递到函数内部具体的数据
(前面1.3.3已经有案例了)
当代码执行到函数调用语句的时候:
第一步,先回到函数定义的位置
第二步,传参(用实参给形参赋值)
第三步,执行函数体
第四步,确定函数返回值
第五步,回到函数调用的位置接着往后执行
返回值就是从函数内部传递到函数外部的数据
看执行函数体的时候有没有遇到return,如果遇到return,return后面的值就是函数的返回值;如果没有遇到return,返回值就是None
RIGHT Example:
# 无返回值def func1(): print(100)# 返回值100def func2(): print('hello world!') return 100# 返回值100或者200def func3(n): if n % 2: return 100 else: return 200# 返回值是一个元组(100, 200)def func4(): return 100, 200
获取函数调用表达式的值就是获取函数的返回值(函数调用表达式:调用函数的语句)
(每个函数调用表达式都是有结果,结果就是返回值;所以函数的返回值能做的事,函数调用都能做)
RIGHT Example:
def func1(): print(100)x1 = func1()print('x1:', x1) # x1: Nonedef func2(): print('hello world!') return 100x2 = func2()print('x2:', x2) # x2: 100def func3(n): if n % 2: return 100 else: return 200x3 = func3(3)print('x3:', x3) # x3: 100x4 = func3(4)print('x4:', x4) # x4: 200def func4(): return 100, 200x5 = func4()print('x5:', x5) # x5: (100, 200)
如果实现函数的功能产生了新的数据,我们就应该将新的数据返回
原因:每次调用函数的时候,系统会自动为这个函数创建一个临时的栈区间,用来保存在函数中产生的数据(形参也是保存在这里面)。当函数调用结束的时候,系统会自动释放这块内存(内存中的数据会被删除),只有返回值不会删除。
(1)返回返回值:谁在return后面,谁就是返回值
(2)提前结束函数:执行函数体的时候如果return,函数直接结束
RIGHT Example:
# return写在函数体最后
def func1():
print('====')
print('++++')
print('hello world!')
return 100
x = func1()
print(x)
"""
====
++++
hello world!
100
"""
# return写在函数体中间,后面的语句不执行
def func1():
print('====')
return 100
print('++++')
print('hello world!')
x = func1()
print(x)
"""
====
100
"""
(1)位置参数:以’实参1, 实参2, 实参3, …'的形式存在,通过位置一一对应的方式给形参赋值
RIGHT Example:
def func1(x, y, z):
# x = 10, y = 20, z = 30
print(f'x:{x}, y:{y}, z:{z}')
func1(10, 20, 30) # x:10, y:20, z:30
func1(20, 10, 30) # x:20, y:10, z:30
(1)关键字参数:以’形参1 = 实参1, 形参2 = 实参2, …'的形式存在,直接用=来确定形参和实参的对应关系
RIGHT Example:
def func1(x, y, z):
# x = 10, y = 20, z = 30
print(f'x:{x}, y:{y}, z:{z}')
func1(x=10, y=20, z=30) # x:10, y:20, z:30
func1(y=20, x=10, z=30) # x:10, y:20, z:30
注意:位置参数和关键字参数可以混用,混用的时候位置参数必须在关键字参数的前面
RIGHT Example:
def func1(x, y, z):
# x = 10, y = 20, z = 30
print(f'x:{x}, y:{y}, z:{z}')
func1(10, y=20, z=30) # x:10, y:20, z:30
func1(10, z=30, y=20) # x:10, y:20, z:30
WRONG Example:
def func1(x, y, z):
# x = 10, y = 20, z = 30
print(f'x:{x}, y:{y}, z:{z}')
func1(x=10, 20, 30)
# 报错,SyntaxError: positional argument follows keyword argument
定义函数的时候,可以通过’形参名=值’的方式给参数赋默认值;如果一个形参有默认值,那么在调用函数的时候这个形参可以不用赋值
RIGHT Example:
def func2(x, y, z=30):
print(f'x:{x}, y:{y}, z:{z}')
func2(10, 20) # x:10, y:20, z:30
def func2(x=10, y=20, z=30):
print(f'x:{x}, y:{y}, z:{z}')
func2(100) # x:100, y:20, z:30
func2(100, 200) # x:100, y:200, z:30
func2(100, 200, 300) # x:100, y:200, z:300
func2(y=200, z=300) # x:10, y:200, z:300
注意:定义函数的时候,如果有的参数有默认值有的参数没有,那么没有默认值的参数必须放在有默认值参数的前面
WRONG Example:
def func3(x, y=20, z):
print(f'x:{x}, y:{y}, z:{z}')
# 报错,SyntaxError: non-default argument follows default argument
参数类型说明既可以提示使用者在调用函数的时候该传什么类型的数据;又可以让参数在函数体中使用的时候有代码提示
(1)方法1:没有默认值的参数:形参名:类型名
RIGHT Example:
def func4(str1: str):
str1.upper()
func4('abc')
(2)方法2:给参数赋默认值,默认值的类型就是参数的类型
RIGHT Example:
def func4(str1: str, list1=[]):
str1.upper()
list1.sort()
func4('abc', [20, 1])
(3)返回值类型说明:函数名()->类型名
RIGHT Example:
def func4(str1: str, list1=[]) -> None:
str1.upper()
list1.sort()
func4('abc', [20, 1])
补充:变量类型说明
message = '["abc", "ssff", "23fdsn"]'
list2 = eval(message) # type:list
解决参数个数不确定的问题
定义函数的时候,如果在某个形参前面加*,那么这个参数就变成了不定长参数,调用的时候这个形参可以接受若干个实参
本质:如果形参有*,那么这个参数就会自动变成一个元组,它接收到的所有实参会作为这个元组的元素
RIGHT Example:
def func5(*num):
print(f'num:{num}')
pass
func5() # num:()
func5(10) # num:(10,)
func5(10, 20) # num:(10, 20)
func5(10, 20, 30, 51, 124) # num:(10, 20, 30, 51, 124)
def func6(x, *y):
pass
func6(10)
func6(10, 20, 312, 13)
APPLICATION 定义一个函数,求多个数的和:
def sum1(*num):
s = 0
for x in num:
s += x
return s
print(sum1(10, 20, 30)) # 60
print(sum1(10, 20, 30, 40)) # 100
注意:
带*的不定长参数在传参的时候只能使用位置参数
定长参数和带*的不定长参数混用的时候, *前的定长参数必须用位置参数传参, *后面的定长参数必须用关键字参数传参
WRONG Example:
def func7(x, *y, z):
pass
func7(10, 20, 30, 40)
# 报错,TypeError: func7() missing 1 required keyword-only argument: 'z'
func7(x=10, 20, 30, z=40)
# 报错,SyntaxError: positional argument follows keyword argument
RIGHT Example:
def func7(x, *y, z):
pass
func7(10, 20, 30, z=40)
APPLICATION 强制后面的参数用关键字参数:
def func8(a, *, b):
pass
(了解)
本质:如果形参前有**,那么这个参数就会自动变成一个字典,它接收到的所有实参会作为这个字典的键值对
注意:传参的时候只能用关键字参数传参
WRONG Example:
def func9(**x):
pass
func9(10, 20)
# TypeError: func9() takes 0 positional arguments but 2 were given
RIGHT Example:
def func9(**x):
print(f'x:{x}')
func9() # x:{}
func9(a=10) # x:{'a': 10}
func9(a1=10, a2=30, b1=2, b2=3) # x:{'a1': 10, 'a2': 30, 'b1': 2, 'b2': 3}
语法:
函数名 = lambda 形参列表: 返回值
相当于:
def 函数名(形参列表):
return 返回值
RIGHT Example 求任意两个数的和的匿名函数:
def sum1(num1, num2):
return num1 + num2
x = lambda num1, num2=2: num1 + num2
print(x(10, 20))
print(x(num1=100, num2=200))
print(x(100))
APPLICATION 1 判断指定年份是否是闰年:
is_leap_year = lambda year: (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)
print(is_leap_year(1900))
APPLICATION 2 求个位数最大的元素:
nums = [12, 39, 18, 80, 34]
print(max(nums, key=lambda x: x % 10))
APPLICATION 3 求绝对值最大的元素:
nums = [12, 39, -18, -80, 34]
print(max(nums, key=lambda x: abs(x)))
nums = [12, 39, -18, -80, 34]
print(max(nums, key=lambda x: x if x > 0 else -x))
nums = [12, 39, -18, -80, 34]
print(max(nums, key=lambda x: x ** 2))
注意:匿名函数的本质还是函数;普通函数中的绝大部分内容匿名函数都支持
根据变量作用域不同,可以将变量分为两种:全局变量、局部变量
定义在函数或者类外面的变量就是全局变量(没有定义在函数里面和类里面的变量就是全局变量)
全局变量的作用域:从定义开始到程序结束
RIGHT Example :
# a、b和c都是全局变量
a = 10
print('外面a:', a)
for b in range(3):
c = 20
print('循环里面a:', a)
print('循环里面b:', b)
print('外面b:', b)
print('外面c:', c)
def func1():
print('函数里面a:', a)
print('函数里面b:', b)
print('循环里面c:', c)
func1()
"""
外面a: 10
循环里面a: 10
循环里面b: 0
循环里面a: 10
循环里面b: 1
循环里面a: 10
循环里面b: 2
外面b: 2
外面c: 20
函数里面a: 10
函数里面b: 2
循环里面c: 20
"""
定义在函数里面的变量就是局部变量(形参也是局部变量)
局部变量的作用域:从定义开始到函数结束
WRONG Example :
def func1(d, e):
f = 100
print('函数里面:', d, e, f)
func1(300, 400) # 300, 400, 100
print('函数外面:', d) # 报错,NameError: name 'd' is not defined
print('函数外面:', f) # 报错,NameError: name 'f' is not defined
print('函数外面:', e) # 报错,NameError: name 'e' is not defined
变量能不能使用,看的是使用的时候内存中有没有
定义全局变量的时候,全局变量保存在全局栈区间,程序结束后才会被自动释放
局部变量是保存在函数对应的临时栈区间中,函数调用结束就会被自动释放
global是函数体中的关键字,可以在函数体中修饰变量,让变量在使用和保存的时候都在全局栈区间中进行
(1)函数中修改全局变量的值
RIGHT Example :
aa = 100
bb = 100
def func2():
# 不会修改全局变量aa的值,而是创建一个局部变量aa
aa = 200
print('里面aa:', aa) # 在函数里面使用的是局部变量aa的值,里面aa: 200
# print(bb) # 报错!global修饰变量必须放在使用之前
global bb
bb = 200
print('里面bb:', bb) # 里面bb: 200
func2()
print('外面aa:', aa) # 在函数外面使用的是全局变量aa的值,外面aa: 100
print('外面bb:', bb) # 外面bb: 200
(2)直接在函数中定义全局变量
RIGHT Example :
aa = 100
bb = 100
def func2():
aa = 200
print('里面aa:', aa)
global bb
bb = 200
print('里面bb:', bb)
global cc
cc = 300
func2()
print('外面aa:', aa)
print('外面bb:', bb)
print('外面cc:', cc) # 外面cc: 300
函数就是变量
python中定义函数其实就是在定义一个类型是function的变量,函数名就是变量名
变量能做的事情函数都可以做
RIGHT Example :
def sum1(num1, num2):
return num1 + num2
b = [10, 20, 30]
print(type(b), type(sum1)) #
list1 = [10, b, sum1]
print(list1[-1](10, 20)) # 30
函数的参数是函数
RIGHT Example :
def func1(x):
print(x(10, 20) * 2.2)
def temp(a, b):
return 2.4
func1(temp)
函数的返回值是函数
RIGHT Example :
def func2():
def temp(x):
return 23
return temp
print(func2()(7) + 20)
max(序列, key=函数):按照函数制定的比较规则来获取序列中最大的元素
函数的要求:(1)参数:有且只有一个参数;这个参数代表前面序列中的每个元素
(2)返回值:有一个返回值;返回值就是比较对象
注意:如果一个函数的参数是函数,这个参数有两种传值方式:a.普通函数的函数名 b.匿名函数
RIGHT Example :
# 练习1:求元素的最大值
nums = [10, 29, 87, 34, -231, 72]
print(max(nums))
# 练习2:求元素最大值
nums = [10, 29, 87, 34, -231, 72]
result = max(nums, key=lambda item: item)
print(result)
# 练习3:求个位数元素最大值
nums = [10, 29, 87, 34, -231, 72]
result = max(nums, key=lambda item: item % 10)
print(result)
# 练习4:求绝对值最小的元素
nums = [10, 29, 87, 34, -231, 72]
result = min(nums, key=lambda item: item ** 2)
print(result)
# 练习5:求nums中数值最大的元素
nums = ['235', '-290', '71', '1998', '80']
result = max(nums, key=lambda item: eval(item))
print(result)
# 练习6:将nums中的元素按照十位数的大小从小到大排序
nums = [913, 281, 1765, 92, 802]
nums.sort(key=lambda item: item // 10 % 10)
print(nums)
# 练习7:获取nums中数字和最小的元素
nums = [1002, 908, 99, 76, 502]
# 方法1
def sum7(item):
digit_sum = 0
while item != 0:
digit_sum += item % 10
item //= 10
return digit_sum
result = min(nums, key=sum7)
print(result)
# 方法2
result2 = min(nums, key=lambda item: sum([eval(x) for x in str(item)]))
print(result2)
# 方法3
result3 = min(nums, key=lambda item: eval('+'.join(str(item))))
print(result3)
(1)map(函数, 序列):按照函数制定的规则将原序列转换成新的序列,返回值是map对象,本质是序列
函数要求:a.参数:有且只有1个参数;参数代表后面这个序列中的元素
b.返回值:有1个返回值;返回值就是新序列中的元素
(2)map(函数, 序列1, 序列2)
函数要求:a.参数:有且只有2个参数
b.返回值:有1个返回值;返回值就是新序列中的元素
(3)map(函数, 序列1, 序列2, 序列3)
函数要求:a.参数:有且只有3个参数
b.返回值:有1个返回值;返回值就是新序列中的元素
以此类推
RIGHT Example 1 获取nums中所有元素的个位数:
nums = [128, 239, 87, 96, 102, 91]
result = list(map(lambda item: item % 10, nums))
print(result) # [8, 9, 7, 6, 2, 1]
RIGHT Example 2 合并两个序列:
str1 = 'abcde'
nums = [10, 20, 30, 40, 50]
# ->['a10', 'b20', 'c30', 'd40', 'e50']
result = list(map(lambda item1, item2: item1 + str(item2), str1, nums))
print(result)
注意:reduce在使用之前必须先导入
from functools import reduce
RIGHT Example 1 求列表中所有元素的和:
nums = [10, 30, 20]
result = reduce(lambda i, item: i + item, nums, 0)
print(result)
RIGHT Example 2 求列表中所有元素的积:
nums = [10, 40, 20]
result = reduce(lambda i, item: i * item, nums, 1)
print(result)
RIGHT Example 3 求列表中所有元素个位数的和:
nums = [12, 34, 91]
result = reduce(lambda i, item: i + item % 10, nums, 0)
print(result)
RIGHT Example 4 字符串合并:
nums = [10, 40, 20]
result = reduce(lambda i, item: i + str(item), nums, '')
print(result)
RIGHT Example 5 选出列表中的数字并相加:
list1 = [10, 'abc', '2.4', 'hans', 5.5, 3]
result = reduce(lambda i, item: i + item if type(item) in (int, float) else i, list1, 0)
print(result)
RIGHT Example 6 偶数就取十位,奇数就取个位,最后求和:
nums = [23, 54, 801, 132, 92]
result = reduce(lambda i, item: i + item % 10 if item % 2 else i + item // 10 % 10, nums, 0)
print(result)