欢迎关注博主 Mindtechnist 或加入【Linux C/C++/Python社区】一起探讨和分享Linux C/C++/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。
什么是函数?
函数返回值
变量作用域指的是变量生效的范围,主要分为两类:局部变量和全局变量。
局部变量是定义在函数体内部的变量,只在函数体内部生效。
def testA():
a = 100
print(a)
testA() # 100
print(a) # 报错:name 'a' is not defined
变量a是定义在
testA
函数内部的变量,在函数外部访问则立即报错。
局部变量的作用:在函数体内部,临时保存数据,即当函数调用完成后,则销毁局部变量。——栈变量,自动析构。
全局变量是在函数体内、外都能生效的变量。
# 定义全局变量a
a = 100
def testA():
print(a) # 访问全局变量a,并打印变量a存储的数据
def testB():
print(a) # 访问全局变量a,并打印变量a存储的数据
testA() # 100
testB() # 100
如果在函数内修改全局变量的值,应该怎么做呢,请看下面的例子:
a = 100
def testA():
print(a)
def testB():
'''
# global 关键字声明a是全局变量
global a
a = 200 #这样表示在函数内修改全局变量
'''
a = 200 #定义了一个局部变量,不会修改全局变量的值
print(a)
testA() # 100
testB() # 200
print(f'全局变量a = {a}') # 全局变量a = 100
在函数内操作的都是局部变量,生命周期只在函数内,不会影响全局变量,如果局部变量与全局变量同名,相当于重新创建了一个变量,它和全局变量没有任何关系。要想在函数内操作全局变量,需要加global关键字,加了global声明后,在函数体内部操作的与全局变量同名的变量都是指全局变量。
不加global声明的时候,对于可变对象,虽然在函数体内无法对全局变量重新赋值但是可以通过内部方法改变。
g_var = 10
def change_var():
g_var = 11
global g_var
print(g_var)
这样会报错,因为这样的话,函数体内会有两个重名的变量,一个是全局变量,一个是局部变量,它们俩都叫g_var。
型参与实参的区别:
函数参数主要有以下几种
(1)位置参数
位置参数:调用函数时根据函数定义的参数位置来传递参数。
def user_info(name, age, gender):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
user_info('Su', 20, '女')
使用位置参数传参的时候,传递和定义参数的顺序及个数必须一致。——实参与形参位置一一对应。
(2)关键字参数
函数调用,通过键值对的形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。
def user_info(name, age, gender):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
user_info('Su', age=20, gender='女')
user_info('alex', gender='男', age=16)
注意:函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序。
(3)缺省参数
缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)。
def user_info(name, age, gender='男'):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
user_info('TOM', 20)
user_info('Rose', 18, '女')
函数调用时,如果为缺省参数传值则修改默认参数值;否则使用默认值。
(4)不定长参数
不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹(packing)位置参数,或者包裹关键字参数,来进行参数传递。
包裹位置传递
def user_info(*args):
print(args)
# ('TOM',)
user_info('TOM')
# ('TOM', 18)
user_info('TOM', 18)
注意:传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是包裹位置传递。
包裹关键字传递
def user_info(**kwargs):
print(kwargs)
# {'name': 'TOM', 'age': 18, 'id': 110}
user_info(name='TOM', age=18, id=110)
综上:无论是包裹位置传递还是包裹关键字传递,都是一个组包的过程。
(5)引用
在python中,值是靠引用来传递来的。
我们可以用id()
来判断两个变量是否为同一个值的引用。我们可以将id值理解为那块内存的地址标识。
# 1. int类型
a = 1
b = a
print(b) # 1
print(id(a)) # 140708464157520
print(id(b)) # 140708464157520
a = 2
print(b) # 1,说明int类型为不可变类型
print(id(a)) # 140708464157552,此时得到是的数据2的内存地址
print(id(b)) # 140708464157520
# 2. 列表
aa = [10, 20]
bb = aa
print(id(aa)) # 2325297783432
print(id(bb)) # 2325297783432
aa.append(30)
print(bb) # [10, 20, 30], 列表为可变类型
print(id(aa)) # 2325297783432
print(id(bb)) # 2325297783432
递归是指函数内部自己调用自己,递归具有以下特性:
使用lambda关键字定义,匿名函数没有函数名 – 赋值给变量,通过变量调用匿名函数。
语法格式:lambda 形参:返回值
lambda m_str:m_str+’…’
func = lambda m_str:m_str+’…’
func(‘hello’)
#相当于
def func(m_str):
return m_str+’…’
把函数作为参数传入,这样的函数称为高阶函数,高阶函数是函数式编程的体现。函数式编程就是指这种高度抽象的编程范式。
编程方法论有三种:面向过程、函数式编程、面向对象。
函数式编程: 函数式=编程语言定义的函数+数学意义的函数;函数式就是用编程语言去实现数学函数,这种函数内对象是永恒不变的,没有for循环和while循环,所有循环都由递归实现,也不需要变量去保存状态。
#函数做参数
def func1():
return ‘hello’
def func2(arg)
print(‘arg is - %s’ %arg)
func2(func1)
func2(func1())
#函数做返回值
def func1():
pass
def func2():
return func1
def func3():
return func1()
在python中,函数名加()就表示运行该函数。如果一个函数接收的参数或者返回值是函数名(是函数名,不是加括号的),那么这个函数就是高阶函数。一定要写函数名,不要加(),因为一加()就运行了。
尾调用
尾调用就是指在函数的最后一步(不是最后一行,是最后一步)调用另一个函数。
尾递归调用优化:在函数的最后一步去递归。
Python内置高阶函数
Python内置函数
bytes(‘你好’, encoding=’utf-8’, decode(‘utf-8’)) 对’你好’进行编解码,如果不写,python默认使用utf-8编解码。(ascii/gbk/utf-8)
chr() 获取ascii码 – ord()
dir() 获取对象的属性和方法的名字
divmod(10, 3) 获取10除以3的商和余数
eval() 将字符串中的数据结构提取出来;得到字符串中的数学运算结果。
hash() 得到一个哈希值 - 哈希值的长度固定,通过哈希值不能推出原来的变量值,在同一个程序中同一值的哈希值是不变的。(用途:软件在官网上本身就带一个哈希值,当下载软件后会把哈希值一块下载,下载后会计算一个哈希值,如果两个哈希值相同说明软件在中途没有被篡改,是安全的)
globals() 打印全局变量
locals() 打印局部变量
zip() 把两个序列变成一一对应的关系,返回的结果是可迭代的
max() 高级用法 – 只要是for可迭代,就能通过max取最大值
people = {“su”:17, “liu”:18, “fan”:19}
print(list(max(zip(people.values(), people.keys()))))
#对于键值对,默认是比较key,如果想比较value并打印出键值对
#可以通过zip把键值对翻过来,然后再比较
list()相当于迭代,可以迭代列表中所有元素,print(list())可以迭代打印
max()比较的时候是按照位置一个一个往后比较的,所以字典之间无法比较,因为字典是无序的。
slice() 切片 l[start, end] → s=slice(start, ent) l[s]
import() 通过字符串的方式导入模块
import 导入模块
import test #test就是一个py文件
test.func() #通过.来使用test.py提供的功能
m = __import__(‘test’)
m.func()