函数
1. 函数的概念
函数即一系列代码指令的集合 用于解决特定的问题 可以反复调用
必须先定义 再使用
2. 定义格式
def 函数名():
函数体
3. 调用
直接在需要调用的位置书写函数名即可
"""
函数即一系列代码指令的集合 用于解决特定的问题 可以反复调用
必须先定义 再使用
"""
# 以下代码 虽然可以实现需求 但是书写非常啰嗦 代码存在 冗余
print("床前明月光")
print("----------")
print("疑是地上霜")
print("----------")
print("举头望明月")
for _ in range(10):
print("-",end="")
print()
print("低头思故乡")
for _ in range(10):
print("-",end="")
print()
"""
函数即一系列代码指令的集合 用于解决特定的问题 可以反复调用
必须先定义 再使用
使用函数优化诗句打印:将重复的内容提取出来 书写为函数 再需要使用的位置 多次调用即可
函数的定义格式:
函数名遵循小写蛇形命名法 与变量一致
def 函数名():
函数体
函数的调用:函数必须调用才会执行 在需要调用函数的位置 直接书写函数名即可
"""
def print_sign():
for _ in range(10):
print("-", end="")
print()
print("床前明月光")
print_sign()
print("疑是地上霜")
print_sign()
print("举头望明月")
print_sign()
print("低头思故乡")
print_sign()
4. 参数
继续优化:可以让调用者灵活的控制符号的数量
通过参数实现:函数的调用者与函数的定义之间传递的数据 称之为参数 形参:形式参数 函数定义的时候书写的参数 属于形参 实参:实际参数 函数调用的时候传入的参数 属于实参
定义了形参以后 必须传入对应个数的实参 除非形参有默认值 否则运行报错
"""
继续优化:可以让调用者灵活的控制符号的数量
通过参数实现:函数的调用者与函数的定义之间传递的数据 称之为参数
形参:形式参数 函数定义的时候书写的参数 属于形参
实参:实际参数 函数调用的时候传入的参数 属于实参
定义了形参以后 必须传入对应个数的实参 除非形参有默认值 否则运行报错
"""
def print_sign(num):
for _ in range(num):
print("-", end="")
print()
print("床前明月光")
print_sign(7)
print("疑是地上霜")
print_sign(10)
print("举头望明月")
print_sign(20)
print("低头思故乡")
print_sign(85)
继续优化:可以让调用者灵活的控制符号的数量 以及 符号的类型
对于函数定义的时候,参数的数量结合具体需求定义即可,没有限制
"""
继续优化:可以让调用者灵活的控制符号的数量 以及 符号的类型
对于函数定义的时候,参数的数量结合具体需求定义即可,没有限制
"""
def print_sign(num,sign):
for _ in range(num):
print(sign, end="")
print()
print("床前明月光")
print_sign(7,"A")
print("疑是地上霜")
print_sign(10,"&")
print("举头望明月")
print_sign(2,"hello")
print("低头思故乡")
print_sign(8,"*")
5.传参规则
关于参数的传递细节 位置参数 关键字参数 解包传参
5.1 位置和关键字参数
"""
关于参数的传递细节
位置参数
关键字参数
解包传参
"""
def print_sign(num,sign):
for _ in range(num):
print(sign, end="")
print()
print("床前明月光")
print_sign(7,"^") # 位置参数 严格按照位置的顺序传入
print("疑是地上霜")
print_sign(num = 10,sign = "&")
print("举头望明月")
print_sign(sign = "&",num = 10)
print("低头思故乡")
print_sign(8,sign = "*")
# print_sign(num = 8,"*") 不能这样书写 报错 关键字参数必须在位置参数后边
5.2 解包传参
"""
关于参数的传递细节
解包传参
"""
def func(a,b,c):
print(a,b,c)
func(1,2,3)
func(a=1,b=2,c=3)
func(1,2,c=3)
list1 = [2,1,3]
func(*list1)
tuple1 = (2,1,3)
func(*tuple1)
set1 = {2,1,3}
func(*set1) # 实际工作中不用 因为顺序无法保证
# 字典解包传参 其实是处理为了关键字参数
# 所以 字典中的键的名字必须和形参的名字完全一致 对照 数量相同
# 顺序无所谓 因为关键字参数 本身就没有顺序要求
dict1 = {"b":2,"a":1,"c":3}
func(**dict1)
func(b = 2,a = 1,c = 3)
5.3 可变长参数
"""
可变长参数 以及 默认值参数
"""
def func1(a,*nums):
print(a,nums)
func1(1,2,3,4,5)
func1(1,2)
# 如果在可变长参数之后还有参数 必须通过关键字参数的方式 进行传递
def func2(a,*nums,b):
print(a,nums,b)
func2(1,2,3,4,5,b = 66)
5.4 默认值参数
def func3(a=1,b=True):
print(a,b)
func3() # 有默认值的参数 可以不传 将使用默认值
func3(2,False) # 也可以传入新的值 覆盖默认值
5.5 强制使用位置或者关键字
强制使用位置或者关键字参数 /之前 必须为位置参数 *之后 必须为关键字参数 中间的 无所谓
"""
强制使用位置或者关键字参数
/之前 必须为位置参数
*之后 必须为关键字参数
中间的 无所谓
"""
def func1(a,b,/,c,d,*,e,f):
print(a,b,c,d,e,f)
func1(1,2,3,4,e=5,f=6)
func1(1,2,3,d= 4,e=5,f=6)
func1(1,2,c= 3,d= 4,e=5,f=6)
# func1(1,2,c= 3,4,e=5,f=6) 这里报错 关键字参数必须在位置参数后边
# func1(1,b = 2,c= 3,d= 4,e=5,f=6) # 报错 因为b必须使用位置参数
# func1(a = 1,b = 2,c= 3,d= 4,e=5,f=6) # 报错 因为a b必须使用位置参数
5. 参数的传递
关于参数的传递 底层细节
在Java语言中分为值传递和引用传递 比如 10 这种数值属于值传递 而 对象这种属于引用传递
Python中的严格来讲 是没有值传递和引用传递的说法 因为在python中所有的数据全部属于对象 都属于引用传递 在函数体内对参数的修改是否会影响原变量 完全取决于是可变类型 还是 不可变类型
"""
关于参数的传递 底层细节
在Java语言中分为值传递和引用传递 比如 10 这种数值属于值传递 而 对象这种属于引用传递
Python中的严格来讲 是没有值传递和引用传递的说法
因为在python中所有的数据全部属于对象 都属于引用传递
在函数体内对参数的修改是否会影响原变量 完全取决于是可变类型 还是 不可变类型
"""
def func1(a):
a += 1
print("func1函数中a的取值:",a)
b = 10
func1(b)
print("实参参数b的取值:",b)
print("-----------------------------------------------------------------")
def func2(nums):
nums[0] += 1
print("func2函数中nums的取值为:",nums)
list1 = [1,2,3]
func2(list1)
print("list1的元素值为:",list1)
print("-----------------------------------------------------------------")
# 直接将一个列表赋值给另外一个列表 属于直接将堆内存中的地址值进行了复制
def func3(nums):
nums[0] += 1
print("func3函数中nums的取值为:",nums)
list1 = [1,2,3]
list2 = list1
func2(list2)
print("list1的元素值为:",list1)
print("list2的元素值为:",list2)
print("-----------------------------------------------------------------")
# 深拷贝 从外到内 都创建新的对象
import copy
list1 = [1,2,3]
list2 = copy.deepcopy(list1)
func2(list2)
print("list1的元素值为:",list1)
print("list2的元素值为:",list2)
print("-----------------------------------------------------------------")
# 浅拷贝 外层的列表 复制全新 里边的元素 用的是同一个
list1 = [1,2,3]
list2 = list1.copy()
list3 = list1[:]
print(id(list1),id(list2),id(list3))
5.1 直接赋值

print("----------------------直接赋值 属于复制的地址值--------------------------")
list1 = [1,2,3,4,5,6]
list2 = list1
print(list1)
print(list2)
print(id(list1),id(list2))
5.2 浅拷贝

print("----------------------浅拷贝 创建新的外层对象 内层对象继续复用--------------------------")
list1 = [1,2,3,[4,5,6]]
list2 = list1.copy()
print(list1,list2)
print(id(list1),id(list2))
print(list1[0] is list2[0])
print(id(list1[0]),id(list2[0]))
print(list1[1] is list2[1])
print(id(list1[1]),id(list2[1]))
print(list1[2] is list2[2])
print(id(list1[2]),id(list2[2]))
print(list1[3] is list2[3])
print(id(list1[3]),id(list2[3]))
5.3 深拷贝

print("----------------------深拷贝 从外到内 全部是新的 --------------------------")
import copy
list1 = [1,2,3,[4,5,6]]
list2 = copy.deepcopy(list1)
print(list1,list2)
print(id(list1),id(list2))
print(list1[0] is list2[0])
print(id(list1[0]),id(list2[0]))
print(list1[1] is list2[1])
print(id(list1[1]),id(list2[1]))
print(list1[2] is list2[2])
print(id(list1[2]),id(list2[2]))
print(list1[3] is list2[3])
print(id(list1[3]),id(list2[3]))
6. 返回值
有些函数在执行的时候,需要有返回值给调用者,通过return关键字进行返回,返回到函数调用的位置。
return 用于在函数体内返回结果 返回给函数的调用者
return表示结束函数并且返回内容
6.1 为什么要用返回值
"""
有些函数在执行的时候,需要有返回值给调用者,通过return关键字进行返回,返回到函数调用的位置。
需求:编写函数计算两个整数之和 在函数之外判断最终的结果是奇数还是偶数
return 用于在函数体内返回结果 返回给函数的调用者
return表示结束函数并且返回内容
"""
def my_sum(a,b):
result = a + b
print("a与b之和为:",result)
get_data = my_sum(2,2)
print(get_data)
if 4 % 2 == 0:
print("偶数")
else:
print("奇数")
# 以上代码可以实现求和 但是 无法在后续的代码中利用最终的和 所以无法进行判断 相当于逻辑无法串联
# 如何解决以上问题?使用return关键字 返回值实现
print("--------------------------------------------------------")
def my_add(a,b):
result = a + b
print("a与b之和为:", result)
return result
print("函数继续执行") # 在Java代码中这里就报错 但是在Python中不报错 但同样永远执行不到
get_num = my_add(13212421421,2)
if get_num % 2 == 0:
print("偶数")
else:
print("奇数")
6.2 return的各种用法
"""
return关键字的其他用法
"""
def is_even(num):
# if num % 2 == 0:
# return "偶数"
# else:
# return "奇数"
return "偶数" if num % 2 == 0 else "奇数"
print(is_even) # 只写函数名 属于打印函数对象 展示函数的基本信息
print(is_even(10)) # 调用函数 并且得到返回值交给print函数打印
print(is_even(11)) # 调用函数 并且得到返回值交给print函数打印
def is_even1(num):
# if num % 2 == 0:
# return True
# else:
# return False
return num % 2 == 0
print(is_even1(10)) # 调用函数 并且得到返回值交给print函数打印
print(is_even1(11)) # 调用函数 并且得到返回值交给print函数打印
def is_even2(num):
# if num % 2 == 0:
# return 0
# else:
# return 1
return num % 2
print(is_even2(10)) # 调用函数 并且得到返回值交给print函数打印
print(is_even2(11)) # 调用函数 并且得到返回值交给print函数打印
print("-----------------------------------------------------------------------")
def func():
for i in range(10):
if i == 8:
return # 注意和break的区别
print(i)
print("func函数执行完毕")
func()
6.3 返回多个值
"""
return关键字的其他用法
return 后边返回多个值
使用多个变量分别接收各个返回值 这个操作 也属于解包
"""
def func():
return 1 , 2 , 3 , [4,5,6]
r1 = func() # 只写一个变量接收 所有的返回值将会自动被打包成一个元组
print(r1)
a1 , a2 , a3 , a4 = func() # 书写对与返回值应数量的变量接收 分开处理 这种也属于解包操作
print(a1, a2, a3, a4)
# b1 , b2 = func() # 这里报错 不允指定不同数量的变量接收
# print(b1, b2)
print("-------------------------------------------------------------")
def func_1(a,b,c):
print(a,b,c)
list1 = [1,2,3]
func_1(*list1)
7. 多级调用
"""
自定义的函数之间 直接调用
栈 stack 先进后出 后进先出 FILO
函数执行是要进栈的 栈属于一种数据结构 先进栈的 后出栈
"""
def my_func2():
print("my_func2 开始执行")
print("my_func2 执行完毕")
def my_func1():
print("my_func1 开始执行********")
my_func2()
print("my_func1 执行完毕********")
my_func1()
8. 递归

"""
递归:recursive 递进和回归
简单的理解:函数自己调自己
准确的理解:
一个大的问题可以通过逻辑拆分为若干个小的问题 可以通过一个函数自己调用当前函数实现
必须有结束的条件 (递归的出口)
举例:
赵四 广坤 小宝 富贵 大拿
递归的实际应用:
求 1 ~ n 之和
求阶乘
很多算法都会用到递归 快排 归并
斐波那契数列
八皇后算法
遍历文件
汉诺塔问题
"""
# def func1():
# func1()
#
# func1() 这段代码 报错 因为没有结束条件
print("-------------------------求1~5之和 非递归实现---------------------------------")
def get_num5():
return 5 + get_num4()
def get_num4():
return 4 + get_num3()
def get_num3():
return 3 + get_num2()
def get_num2():
return 2 + get_num1()
def get_num1():
return 1
print(get_num5())
print("-------------------------求1~n之和 递归实现---------------------------------")
def get_sum(num):
if num == 1:
return 1
return num + get_sum(num - 1)
print(get_sum(5))
print(get_sum(6))
print(get_sum(100))
print("-------------------------求阶乘 递归实现---------------------------------")
def get_factorial(num):
if num < 1 or num == 1:
return 1
return num * get_factorial(num - 1)
print(get_factorial(5))
9. lambda表达式
lambda 匿名函数 面向函数编程 不关注谁来做 只关注做什么
9.1 介绍
"""
lambda 匿名函数 面向函数编程 不关注谁来做 只关注做什么
ctrl + alt + L 自动格式化对齐代码
"""
def add(a, b):
return a + b
def sub(a, b):
return a - b
def mul(a, b):
return a * b
def div(a, b):
return a / b
def operation(a,b,func):
return func(a,b)
print(add)
print(sub)
print(mul)
print(div)
print(operation(1, 2, div))
print("*" * 50)
print(operation(1, 2, lambda a, b: a + b))
print(lambda a, b: a + b)
print(type(lambda a, b: a + b))
9.2 常用函数
"""
lambda主要的作用 用于处理数据的 是一种语法简洁的优化形式
使用lambda处理数据
"""
from functools import reduce
# list1 = [2,1,4,6,3]
# list1.sort(reverse=True)
# print(list1)
# print(sorted(list1,reverse=True)) 排序操作 reverse=True 表示降序
person_list = [
{"name":"jack","age":21,"address":"深圳"},
{"name":"jeery","age":11,"address":"深圳"},
{"name":"tom","age":35,"address":"广州"},
{"name":"john","age":25,"address":"广州"},
{"name":"lily","age":55,"address":"东莞"}
]
print("-------------------------sorted函数 排序-------------------------------")
# 按照年龄升序或者降序排序 reverse=True 表示降序
print(sorted(person_list,key=lambda p : p["age"],reverse=True))
print(sorted(person_list,key=lambda p : p["name"]))
print("-------------------------map函数 映射-------------------------------")
# 呈现每个人姓名的大写形式
print(list(map(lambda p: p["name"].upper(), person_list)))
print("-------------------------filter函数 过滤-------------------------------")
# 查找地址为深圳的人
print(list(filter(lambda p: p["address"] == "深圳", person_list)))
# 查找未成年的人
print(list(filter(lambda p: p["age"] < 18, person_list)))
print("-------------------------reduce 函数 合并操作-------------------------------")
print(reduce(lambda x, y: x + y, [1, 2, 3, 4, 5]))
# 统计列表中所有人的年龄总和
# print(reduce(lambda p1, p2: p1["age"] + p2["age"], person_list)) # 这里报错 因为年龄相加之后 无法直接赋值给某个字典对象
person_list = [
{"name":"jack","age":21,"address":"深圳"},
{"name":"jeery","age":11,"address":"深圳"},
{"name":"tom","age":35,"address":"广州"},
{"name":"john","age":25,"address":"广州"},
{"name":"lily","age":55,"address":"东莞"}
]
print(reduce(lambda total_age, p1: p1["age"] + total_age, person_list,0))
10. 函数的注释(了解)
"""
多行注释 本质实现为字符串
"""
def dog(name:str, age:(1, 99), species:'狗狗的品种') -> tuple:
"""
这个函数用于讲解函数的注释
:param name: 这是名字参数
:param age: 年龄参数
:param species: 品种参数
:return: 返回值
"""
print(name,age,species)
return True
dog(123,"abc",True)
print(dog.__annotations__)
help(dog)