01 recode
1. 函数的声明(声明函数的时候不会执行函数体)
def 函数名(参数列表):
函数的说明文档 ---> 放在引号注释里,注释说明函数功能
函数体
参数列表中的阐述可以进行参数类型说明(只是进行说明,没有强制限制类型,但一般不要违反)可以通过 参数名: 类型名 来指定参数的类型,也可以通过设置默认值来说明参数的类型
def 函数名(参数1: int, 参数2=[])
-
说明类型的好处:
a. 传什么类型参数一目了然
b. 实现函数体时有相应的代码提示 return 也可以进行说明
def 函数名(参数1: int, 参数2=[]) ->返回值类型:
2. 函数的调用
- 格式:
函数名(实参列表)
-
调用过程:
第一步:回到函数声明的位置
第二步:用实参给形参赋值 ---> 传参(保证每个参数都要有值)
第三步:执行函数体
第四步:确定返回值 ---> 将函数调动表达式设置为返回值
第五步:回到函数调用的位置,接着往后执行
3. 函数的参数
-
分类
位置参数
关键字参数
参数的默认值 ---> 有默认值的参数要放在没有默认值的参数后面
不定长参数 ---> 在参数前面加 * 下面有补充
def func1(a: int, b=[]):
"""
把参数a 添加到列表b中
:param a:
:param b:
:return:
"""
b.append(a)
return b
print(func1(1, [1, 2, 3])) #[1, 2, 3, 1]
-
补充:不定长参数(面试题)
-
说说*args, **kwargs之间的区别
args 就是参数名前加一颗, 将位置参数作为元组的元素,参数就是一个元组
kwargs 就是参数名前加两颗,必须以关键字的方式传参,然后将关键字参数转换为字典
注意:经常将 *args 和 **kwargs放在一起组合使用,但是使用的时候,两颗星的要放在后面传参数的时候,关键字参数也要放在位置参数后面
def func2(*args, **kwargs):
print(args, kwargs, sep = "\n")
func2(1, 2, 3, 4, {"b": 1}, a = 12) # (1, 2, 3, 4, {"b": 1}), {"a": 12}
func2(1, 2, 3) # (1, 2, 3) {}
func2(a = 1, b = 2, c = 3) # () {"a": 1, "b": 2, "c": 3}
4. 返回值
python中所有的函数都有返回值,默认的返回值是None,如果遇到return,函数的返回值就是return后面的值
返回值就是函数调用表达式的值
调用函数的目的:a. 执行函数体 b. 获取返回值
函数调用表达式: fun_x(实参)
-
return的作用: a. 返回返回值 b. 结束函数(函数中遇到return就结束函数)
02 匿名函数
-
- 普通函数:
def 函数名(参数列表):
函数体
-
- 匿名函数:
函数名(变量名) = lambda 参数列表:返回值
- 说明:
a. 函数名 ---> 变量名
b. lambda ---> 声明匿名函数的关键字
c. 参数列表 ---> 由多个参数组成,至少有一个
d. 返回值 ---> 相当于只有一个return语句的函数体
匿名函数的调用和普通函数一样,支持位置参数, 关键字参数, 参数也可以设置默认值, 支持不定参数
- 特点:
直接将函数的声明作为一个值存到一个变量
将函数声明赋给一个变量
# 求两数之和
sum_num = lambda x, y: x + y
print(sum_num(10, 20)) # 30
# 求1+2+……n的和
sum_nums = lambda n: sum(range(n+1))
print(sum_nums(100)) # 5050
sum1 = lambda *num:sum(num)
print(sum1(1, 2, 3)) # 6
# 练习:读程序
funcs = []
for item in range(1, 5): # 执行完循环 funcs = [lambda x: x * item, lambda x: x * item, lambda x: x * item, lambda x: x * item]
funcs.append(lambda x: x * item) # 循环结束后item = 4
print(funcs[0](2)) # 8
print(funcs[1](2)) # 8
03 变量的作用域
-
- 变量的作用域
变量的作用域指的是变量能够使用的范围
- 变量的作用域
-
- 全局变量
全局变量:声明在函数和类的外面的变量都是全局变量;
作用域:作用域是从声明开始到整个Py文件结束都可以使用
- 全局变量
-
全局变量 a 、 b 、 x 都是全局变量,只有涉及函数和类里面的变量才是局部的
a = 10
print("=====")
for x in range(2):
b = 5
print(a) # 10 10
if True:
print(a) # 10
print(a) # 10
print("=====")
-
- 局部变量
声明在函数和类中的变量都是局部变量,声明在函数的局部变量,作用域从声明开始到整个函数结束,只能在函数局部使用
- 局部变量
def func1():
aa = 100
bb = 200
# print(aa, bb) 报错,aa和bb没有被定义
-
- global关键字
只能在函数里用:在函数中声明一个全局变量
- global关键字
name = "abc"
def func2():
global name # 说明当前函数中使用的name是全局变量的name
print(name)
name = "aaa"
print(name)
func2() # "abc" "aaa"
print(name) # "aaa"
-
- nonlocal 关键字
def func5():
a1 = 500
# nonlocal a1 # 就算声明a1非局部的也不能在函数外使用,依旧是局限于函数内部的
# global a1 # 就算在函数内声明a1为全局变量,但是只要函数外没有a1被声明,a1也是函数内的
def func6():
nonlocal a1 # 让a1不仅仅作用域在func6(),也可以作用于上一级的函数
print(a1)
a1 = 600
print(a1)
func6()
print(a1)
func5() # 500 600 600
04 函数作为变量
声明函数就是声明一个类型是function的变量,函数名是指就是变量名
def func1():
print("========")
print(type(func1)) # Class 'function'
# print(func1) # 打印出 function func1 at oxoo6155d0 打印出func1的被存于oxoo6155d0
-
- 变量能给其他变量赋值
a = 10 # 普通变量赋值
b = a
print(b * 10) # 100
list1 = [1, 2]
list2 = list1[:]
print(list2*2) # [1, 2, 1, 2]
# 函数给变量赋值
def func2():
print("我是函数")
x = func2 # 将func2 赋值给x
x() # "我是函数"
print(type(x)) # class "function"
func3 = lambda x: print(x) # 将func3赋值给y
y = func3
y(2) # 2
-
- 函数作为列表的元素
a = 10
list4 = [1, a]
print(list4, list4[1] + 100) # [1, 10] 110
def func10():
print("我是函数")
return 10
print("----------")
list5 = [1, func10, func10()] # list5[2] 首先会调用函数打印,之后将返回值存在列表中
print(list5) # [1, func10, 10]
print("========================")
print(list5[1]()) # 调用函数执行打印 "我是函数",然后打印出函数的返回值 10
-
- 将函数作为参数
print("==--==--==--==--==--==--")
a = 10
def func_a(n): # 往函数中传普通变量
print(n)
func_a(a) # 10
# 给函数传函数
def func_b(n):
# n = func_c
n() # 执行 func_c(),打印出 "hello python"
def func_c():
print("hello python")
func_b(func_c) # "hello python"
-
应用:sort的使用
列表.sort(key=None, reverse=False)
使用sort时,可以给key赋一个函数变量来规定函数用什么标准来排序,这儿的函数变量要求要有一个参数和一个返回值,参数代表列表中的元素,返回值代表按照那个标准排序
list1 = [1, 2, 55, 33] # 列表中可以直接排序
list1.sort()
print(list1) # [1, 2, 33, 55]
list2 = [{"name": "张三", "age": 20, "grades": 90}, # 列表中有多个元素用key排序
{"name": "李四", "age": 18, "grades": 99},
{"name": "王二麻子", "age": 32, "grades": 77}]
def key_age(item):
return item["age"] # [{"name": "李四", "age": 18, "grades": 99}, {"name": "张三", "age": 20, "grades": 90}, {"name": "王二麻子", "age": 32, "grades": 77}]
# list2.sort(key=lambda item: item["age"])
list2.sort(key=key_age) #根据年龄排序
print(list2)
# 让list3以第二个元素倒序排列
# method one
list3 = [(10, 2), ("c", 23), (33, 44)]
def key_2(item):
return item[1]
list3.sort(key=key_2, reverse=True)
print(list3) # # [(33, 44), (23, "c"), (10, 2)]
# method two
list3 = [(10, 2), ("c", 23), (33, 44)]
list3.sort(key=lambda item: item[1], reverse=True)
print(list3)
-
- 将函数作为返回值
根据运算符,返回运算符对应的功能 功能对应的就是函数
def operation(operator: str):
if operator == "+":
def func1(*args, **kwargs): # func1 相加功能
"""
求和功能
:param args: (1, 2)
:param kwargs: {"a": 3, "b", 4}
:return:
"""
sum1 = 0
for item in args:
sum1 += item
for keys in kwargs:
sum1 += kwargs[keys]
return sum1
return func1
elif operator == "*":
def func2(*args, **kwargs): # func2 相乘功能
"""
xiang功能
:param args: (1, 2)
:param kwargs: {"a": 3, "b", 4}
:return:
"""
sum1 = 1
for item in args:
sum1 *= item
for keys in kwargs:
sum1 *= kwargs[keys]
return sum1
return func2
f1 = operation("+") # f1 = func1,f1就是具有两个不定长参数的有求和功能的函数
re = f1(1, 2, a=3, b=4)
print(re) # 10
# print(operation("+")(1, 2, a=3, b=4))
f2 = operation("*") # f2 =func2
re = f2(1, 2, a=3, b=4)
print(re) # 24
# print(operation("*")(1, 2, a=3, b=4))
05 函数的调用
-
- 补充: python中的函数可以有多个返回值
求多个数的和以及平均值
def sum_num(*nums):
sum1 = sum(nums)
average = sum1 / len(nums)
return sum1, average # 同时返回和、平均值
a, b = sum_num(2, 35, 6, 33, 76)
num = sum_num(2, 35, 6, 33, 76) # 返回的num为一个元组
print(a, b) # 152 30.4
print(num[0], num[1], num) # 152 30.4 (152, 30.4)
-
- 函数的调用过程是一个压栈的过程
每次调用函数的时候,系统都会在内存中(栈)开辟空间来存储函数执行过程中产生的数据(形参、声明的变量),当函数调用完成后,这块内存会自动销毁栈内存特点:申请和释放由系统完成
06 递归函数了解一哈
-
- 什么是递归函数(会导致内存在一段时间猛增猛减,消耗cpu资源)递归函数:函数中调用函数本身,这样的函数就是递归函数(自己调用自己)
循环能做的事情,递归都可以做,但是实际上循环能解决的事情,绝对不选递归
def func1():
print("===")
func1()
# func1() 达到最大递归次数,内存不够 maximum recursion depth exceeded while calling a Python object
-
- 怎么写递归函数
第一步 确定临界值(循环结束的条件),让函数结束
第二步 找关系,假设函数功能已经实现,找f(n)和f(n-1)的关系
第三步 根据关系,用f(n-1)实现f(n)的功能
写递归函数,实现1+2+3+...n
def ey_sum(n):
# 1. 找临界值
if n == 1:
return 1
# 2. 找关系
# ey_sum(n) = 1+2+3+……n
# ey_sum(n-1) = 1+2+3+……n-1
# ey_sum(n) = ey_sum(n-1) + n
# 3. 用f(n-1)实现f(n)功能
return ey_sum(n-1) + n
print(ey_sum(5)) # 15
- 调用过程:
ey_sum(5) return ey_sum(4) + 5 1 + 2 + 3 + 4 + 5
ey_sum(4) return ey_sum(3) + 4 1 + 2 + 3 + 4
ey_sum(3) return ey_sum(2) + 3 1 + 2 + 3
ey_sum(2) return ey_sum(1) + 2 1 + 2
ey_sum(1) return 1
用递归实现以下功能
n = 3
打印
***
**
*
def ey_star(n):
if n == 1:
print("*")
return
print("*"*n)
ey_star(n - 1)
ey_star(5) # *****
# ****
# ***
""" # **
n = 3 # *
打印
*
**
***
"""
def ey_print(n):
if n == 1:
print("*")
return
ey_print(n - 1)
print(n*"*")
ey_print(5) # *
# **
# ***
# ****
# *****