自定义函数
之前我们接触了很多的内置函数。函数可以极大提高工作效率
一、一般函数
函数特性
- 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
- 函数能提高应用的模块性,和代码的重复利用率。
函数规则如下:
- 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
- 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
- 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
- 函数内容以冒号起始,并且缩进。
- return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None
- 我们用之前的一个例子做比较。通过产品ID来查找产品的价格。如果这个代码按照之前写的。在别的模块里面或者别的同事需要用到的时候。只能完整的拷贝这些代码了。而如果自定义写个函数。那么完全不需要关心函数内部是这么实现的。也不需要拷贝所有的代码。只需要调用这个函数传入ID就好了。代码的复用率得到很大的提升。对于项目级别的代码。这是非常明显的。
“”“
id_price_ = {
1: 180,
2: 90,
3: 100,
4: 50
}
bzf_ = True
while bzf_:
product_id = input('请输入产品id:')
if int(product_id) in id_price_:
print('产品价格:' + str(id_price_[int(product_id)]))
bzf_ = False
break
else:
print('产品不存在!请重新输入')
”“”
# 自定义函数实现的过程如下
# def 函数声明
# find_product 函数名称
# product_id 函数参数
# return 函数返回结果
# 中间的代码块称为函数主体
def find_product(product_id):
"""
查询产品价格
:param product_id:产品id
:return: 产品价格
"""
_id_price = {
1: 180,
2: 90,
3: 100,
4: 50
}
if int(product_id) in _id_price:
return _id_price[int(product_id)]
else:
return ('产品不存在!请重新输入')
print(find_product(222))
print(find_product(2))
打印结果:
产品不存在!请重新输入
90
- 函数嵌套函数
def qt(m):
def qths():
return 333
n = m + qths()
return n
qt(111)
函数的几种参数
- 必填参数
- 默认参数
- 不定长元组参数
- 关键字参数
def demo1(cs1, cs2='不传值为默认值'):
print(cs1)
print(cs2)
demo1('参数1')
def demo2(*args, **kwargs):
"""
特殊参数演示
:param args: 不定长元组参数
:param kwargs: 关键字参数
:return:
"""
print(args,type(args))
print(kwargs,type(kwargs))
demo2('不定长参数元素1', '不定长参数元素2', key1='11', key2=22)
打印结果:
参数1
不传值为默认值
('不定长参数元素1', '不定长参数元素2') <class 'tuple'>
{'key1': '11', 'key2': 22} <class 'dict'>
- 变量在函数内部的作用域。函数外部的变量在同一文件中是全局的。函数可以直接使用该变量。但是当函数内部变量名称和函数外部名称一致时。在没声明函数内的变量是全局的话。2个变量之间没有任何关系。在嵌套函数中,如果要修改主函数的变量。可以使用nonlocal
a = 2
c = 3
def m(x):
a = 3
y = x + a + c
return y
print(m(3),a)
b = 3
def n(z):
global b # 声明 b 的作用域为全局
b = 5 # 因为b是全局变量。当函数内b的值改变了。函数外的b的值也改变了。
q = z+b
return q
print(n(4),b)
def q():
u = 5
def r():
nonlocal u # 声明 u的作用域是整个函数
u = 6
r()
return u
print(q())
参数的传递
- 函数的入参如果是不可变的数据类型。重新赋值该入参。只不过是新创建了一个变量。和原始参数没有任何关系。
- 函数的入参如果是可变的数据类型。该变量值发生变化。原始参数也会跟着变化。因为他们自始至终都指向同一个对象。
a = 1
b = [1,2,3,4]
def n(x,y):
x = 3
y.append(x)
return d
n(a,b)
print(a,b)
二、几种特殊的函数
闭包函数是函数嵌套的一种特殊方式。规则如下:
- 必须有一个嵌套函数(函数内部的函数)。
- 嵌套函数必须引用封闭函数中定义的值。
- 闭包函数必须返回嵌套函数。
# 计算一个数的平方
def c(i):
def nested():
b = i ** 2
return b
return nested
递归函数
- 在函数的执行过程中不断的调用函数本身。
def call(n):
print(n)
if int(n/2) >0:
call(int(n/2))
else:
print('~~~~~')
print(n)
call(10)
猜猜这个结果是什么??
- 在使用递归函数的时候。一定要遵循一下原则。
- 必须有一个明确的结束条件,要不就会变成死循环了,最终撑爆系统
- 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
- 递归执行效率不高,递归层次过多会导致栈溢出。(实际测试超过了996次递归基本就会溢出了)
匿名函数
- python 使用 lambda 来创建匿名函数。所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。
- lambda 只是一个表达式,函数体比 def 简单很多。
- lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
- lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
# 一般的函数和匿名函数实现相加的功能
def demo(cs1,cs2):
return cs1+cs2
sum = lambda cs1,cs2:cs1+cs2
print(demo(1,2))
print(sum(1,2))