目录
1、函数:
定义:实现某一功能的代码块,可随时调用(主要作用:代码重复使用,模块化编程)
函数是一个被命名的、独立的、完成特定功能的代码段,其可能给调用它的程序一个返回值
功能专一,只能实现某一个功能;大多数函数都有名字,也有匿名函数
在Python中,如果只是输出函数名称,返回的是函数的内存地址
如果是函数名称+( ),则是找到这个函数的内存地址并立即执行
函数的创建与使用
## 函数的定义(创建)与使用,必须先定义再使用
# 定义 def 关键字
def 函数名([参数]): # 即使没有参数也要有()
""" 函数的说明文档 """
函数体
return 返回值
# 函数设计原则:'高内聚(只完成一个功能),低耦合(每个函数完成的功能不一样)',
# 函数执行完毕后,应主动把数返回给调用处,而不是使用print直接输出,尽量使用return而不是print
def dazhaohu(name):
'''打招呼'''
# print('你好,'+name)
# 返回值,当该函数被调用时,会把返回值返回到函数的调用位置
return '你好' + name
# 函数的调用
# 函数名(参数)
print(dazhaohu("老张"))
# 查看函数的说明文档 help(函数名)
help(dazhaohu)
# return
# 如果函数里有两个return ,只会执行第一个return
# 因为return可以退出当前函数,导致下方的return代码不执行
def two_return():
return 1
return 2 # 不会被执行
# 如果一个函数想要有多个返回值,可以使用return 元组的形式
def tworeturn():
return 1,2
# pass 空语句,不做任何事情,一般起到占位作用
def func():
pass
## 函数的嵌套 : 一个函数里面又调用了另一个函数
# 例子
def funcB():
print('这是函数B的函数体')
def funcA():
print('——'*40)
print('这是A的函数体部分')
#嵌套
funcB()
print('*'*40)
# 调用只需要调用A
funcA()
# 使用debug调试查看嵌套函数的执行流程时,要使用step in to ↓
2、函数参数
位置参数、关键字参数和缺省参数(默认值参数)
# 形参:函数定义时参数列表中的参数
# 函数的形参的定义顺序是位置参数, 缺省参数,不定长参数
# 实参:函数调用时输入的参数
# 位置参数:在调用函数是,实参数量必须与形参数量一致,指定的实参位置要与形参位置一致
# 关键字参数 :使用形参的名字来确定输入的参数值,此时不要求与形参位置一致(Python特有)
def func(a,b,c):
pass
func(a = 1, c =3, b = 2)
# 缺省参数(默认值参数):在定义函数时,为参数设置默认值,当没有传入参数,就使用默认值
# 指定默认的形参必须放在所有参数的后面
def func(a=1,b=2):
不定长参数(元组、字典)
# 可变参数(不定长参数)
# 接受任意多个参数并将其放到一个 元组 中 *param
# 以位置参数传递
def func(*name):
print(name)
func('a','b','c','d')
# 或
s = ['a','b','c','d']
func(*s)
# 接受任意多个显式赋值参数,将其放到一个 字典 中 **param
# 以关键词参数传递
def func1(**sign):
print(sign)
func1(a= 1 , b='2')
# 或直接使用一个已存在的字典
dict1 ={'a':'1','b': 2 }
func1(**dict1)
## 不定长参数的混合使用
# 如果是两种都用的话,要将不定长字典参数放在后面
def sumfunc(*args, **kwargs):
# 计算所有元素的和
# 先定义一个值
result = 0
# 先遍历 元组 的元素
for i in args:
result += i
# 遍历 字典 所有的value值
for i in kwargs.values():
result += i
return result
print(sumfunc(1, 12, 87, num1=10, num2=23))
3、变量的作用域 ---变量的作用范围
函数内部 ——局部作用域——局部变量
函数外部—— 全局作用域——全局变量
## global 关键字 在函数体内部改变全局变量的值
num = 10 # 全局变量,函数内外都可以访问
def func1():
num = 2 # 局部变量,虽然和全局变量同名,但不影响全局变量的值,尽量不让他们重名
print(num)
# global 关键字
def func1():
# 声明接下来使用的num变量是全局变量
global num
num = 2
print(num)
# 实现多个函数共享数据
students = []
def funcA():
# 如果对全局变量进行修改的话,使用global
global students
students.append(1)
students.append(2)
def funcB():
# 如果只是访问全局变量的话,不需要使用global,直接用
for i in students:
print(i)
funcA()
funcB()
4、Python 拆包
—— 就是将元组或字典中的数据单独的拆分出来,然后赋予给其他变量
# 元组拆包
def return_num():
return 100, 200
num1, num2 = return_num()
print(num1) #100
print(num2) #200
# 原理: return返回多个值时返回的是元组,当函数调用的时候将值返回到函数调用的位置,然后第一个值赋值给左边的第一个变量,第二个值给第二个变量
a = '牛奶'
b = '可乐'
a, b = b, a # 当有多个元素时,不加小括号也是元组
# 此时,将第一个值b赋值给了左边第一个变量,a赋值给了第二个变量
print(a) # 可乐
print(b) # 牛奶
# 字典拆包 只能把 key 给拆出来
dict1 ={'a':'1','b': 2 }
element1, element2 = dict1
print(element1) # a
print(element2) # b
5、可变数据和不可变数据类型
# 总结 : 不可变数据类型:内存地址一旦确定,里面的值就不会发生改变(值一改变,内存地址也会变,尽管是同一个变量)
# 不可变数据类型在赋值后,其中一个值的改变不影响另外一个变量,因为指向的内存地址不同了
不可变类型: 数值型(整型、浮点型)、bool类型、字符串、元组
可变类型: 列表、字典、集合
# 可变类型:就是变量值的改变不影响内存地址,内存地址不会改变
# 引用变量
# 在Python中 值是靠引用来传递的,可以使用id()函数来看两个变量是否为同一个值的引用
# id 的值可以理解为那块内存的地址标识
a = 10
b = a
print((id(a))) #140708447638600
print(id(b)) #140708447638600
#尝试更改a的值
a += 30 #40
print(a)
print(id(a)) #140708447639560 内存地址也变了
#再看 b 的值
print(b) #10
# 总结 : 不可变数据类型:内存地址一旦确定,里面的值就不会发生改变(值一改变,内存地址也会变,尽管是同一个变量)
# 不可变数据类型在赋值后,其中一个值的改变不影响另外一个变量,因为指向的内存地址不同了
# 不可变类型: 数值型(整型、浮点型)、bool类型、字符串、元组
# 可变类型: 列表、字典、集合
# 可变类型:就是变量值的改变不影响内存地址,内存地址不会改变
aa = [10,20]
print(id(aa)) #1837180533312
aa.append(30)
print(aa)
print(id(aa)) #1837180533312
# 可变类型与函数 : 可变类型在函数中,如果在全局或局部中对可变类型进行增删改操作,其外部和内部都会跟着变
def funcA(names):
names.append('王二麻子')
print(names)
list1 = ['张三','李四']
funcA(list1) #['张三', '李四', '王二麻子']
print(list1) #['张三', '李四', '王二麻子']
# 在调用这个函数时,将list1赋值给了name,所以他俩指向同一个内存地址,
# 又因为列表是可变数据类型,所以name的值变了,list1也会变
# 不可变数据类型与函数 : 不会有改变
def funcB(num):
num += 10
return num
a = 10
print(funcB(a)) #20
print(a) #10
6、递归函数
# 递推算法:通过已知条件,利用特定条件得到中间推论,直到得到结果
# 分为 顺推 和 逆推
# 顺推 ;通过条件逐步推结果 逆推 : 通过结果找规律推条件
# 斐波那契数列: 1 1 2 3 5 8...从第三位开始,是前面两个数的和
# n 表示斐波那契数列的第n位
def func(n):
# 斐波那契数列前两位是1 已知条件
if n==1 or n==2:
return 1
# #计算后面的,可以利用字典的形式{第n位:第n位的值}
# #前面两个固定的可以先写出来
# dict1 = {1:1,2:1}
# # 从第三位开始,其结果为前两位数的加和 规律
# for i in range(3,n+1):
# # 利用字典增加元素的方式:字典[key]=value,没有key就会创建
# dict1[i] = dict1[i-1] + dict1[i-2]
#循环结束通过字典访问元素的方式获得第n位的值
#return dict1[n]
# 也可以使用列表
lis = [1,1]
for i in range(2,n+1):
a = lis[i-1]
b = lis[i-2]
i = a+b
lis.append(i)
# # 循环结束通过索引的方式获得第n位的值,因为索引是从0开始的,所以要用减一的索引
return lis[n-1]
# 求第15位的结果
print(func(15))
#############################################
# 递归 : 函数调用自身的编程技巧,通常把一个大的复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
# 两个重要概念 : 递归点 (当前问题的等价函数) ; 递归出口(已到达最优问题,不能再次调用);
# 没有出口就会变成死循环
## 递归三要素: 1,明确函数用来干什么 2,寻找递归结束条件(递归出口) 3,找出函数的等价关系式
# 1,明确函数要做什么 ----求斐波那契第15位的结果
# 2,寻找递归出口 ----- n=1 或 n=2的时候自动中止,因为这是已知条件
# 3, 寻找与问题相关的数学模型 ---- funcx(n) = funcx(n-1) +funcx(n-2)
def funcx(n):
#如果n=1或n=2
if n ==1 or n==2:
return 1
# 与问题相关的最小数学公式
return funcx(n-1) +funcx(n-2)
# 调用函数
print(funcx(15))
# 用递归函数求 n!
# 1,明确函数要干什么 ---求10的阶乘
# 2,寻找递归出口 ----已知条件 1的阶乘为1
def func_jc(n):
#递归出口
# if n ==1:
# return 1
# if n == 2:
# return 2
if n <= 2:
return n
#找最小的表达式 --- n! = n*(n-1)*(n-2)*...*1 ==>>简化为n*(n-1)
return n*func_jc(n-1)
print(func_jc(10))
# 递归求猴子吃桃
# 1,明确函数要干什么 ---求第一天共摘了多少桃
# 2,递归出口 ---已知第10天只有1个桃
# 3,最小数学公式 ----第9天的桃=(第10天的桃+1)/2 f(n) =(f(n+1)+1)*2
def f_tao(n):
if n == 10:
return 1
return (f_tao(n+1)+1)*2
print(f_tao(1))
7、lambda表达式
# lambda表达式 ==> 匿名函数
# 如果一个函数有一个返回值,并且只有一句代码,可以使用lambda简化
# 基本语法
变量 = lambda 函数参数:表达式(函数代码+ return返回值)
# #调用
变量() #记得一定要带小括号,不然输出的是这个函数的内存地址
# 举例 返回100
def func1():
return 100
# 匿名函数:
fn1 = lambda: 100
print(fn1()) # 100
## 带参数的 匿名函数
fn2 = lambda num1, num2: num1 + num2
print(fn2(1, 2)) # 3
## 带默认参数的
fn3 = lambda a, b, c=10: a + b + c
print(fn3(1, 2)) # 13
print(fn3(1, 2, 13)) # 16
## 不定长参数
fn4 = lambda *args: args
fn5 = lambda *kwargs: kwargs
list11 = [1, 5, 9]
dict11 = {'name': '张三', '年龄': 24}
print(fn4(list11)) # ([1, 5, 9],)
print(fn5(dict11)) # ({'name': '张三', '年龄': 24},)
## 带if判断 (三元运算符)
fn = lambda a, b: a if a > b else b
print(fn(3, 7)) # 7
8、列表加字典的排序
###########################
# 列表数据 +字典数据排序(重点) 列表.sort(key=排序的key索引,reverse=True)
# 普通列表数据
list1 = [10, 20, 12, 26, 8, 19]
list1.sort()
print(list1) # [8, 10, 12, 19, 20, 26]
# 列表嵌套字典数据的排序
students = [
{'name': 'Tom', 'age': 12},
{'name': 'Jene', 'age': 22},
{'name': 'Rose', 'age': 20}
]
# 按照name值升序排列(a-z/A-Z)
# sort(key = 按照key指向的value进行排序)
# sort(key = 必须是一个函数),经常与lambda表达式相结合
# students.sort==>系统会首先将students列表中的3个字典元素通过循环遍历的方式一一放入到i变量中
# ==> i就相当于{'name':'Tom','age':12},再通过 i['name'] 来得到对应的value
students.sort(key=lambda i: i['name'])
print(students)
# [{'name': 'Jene', 'age': 22}, {'name': 'Rose', 'age': 20}, {'name': 'Tom', 'age': 12}]
# 按照name值降序排列
students.sort(key=lambda i: i['name'], reverse=True)
print(students)
# [{'name': 'Tom', 'age': 12}, {'name': 'Rose', 'age': 20}, {'name': 'Jene', 'age': 22}]