目录
函数
在一个完整的项目中,某些功能会反复的使用,会产生很多重复的代码。将重复使用的代码封装成函数,当我们要使用此功能时调用即可。这样可以复用代码,增加代码的可维护性。
定义函数
以 def 关键词开头,后接函数标识符名称和圆括号()。
任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None
def func(*args,**kv):
...
return ret_val
import math
def get_area(r, h): # 计算圆柱的面积
area = math.pi*r**2*h
return area
print(get_area(5, 10)) # 输出785.3981633974483
函数参数:
参数顺序基本原则:位置参数,默认参数,可变长位置参数,可变长关键字参数。
- 位置参数:调用函数时根据函数定义的参数位置来传递参数。
- 默认参数:调用函数时,默认参数的值如果没有传入,则被认为是默认值。
- 关键字参数:通过“键=值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。
- 可变长位置参数*args:加了星号(*)的变量名会存放所有未命名的变量参数。
- 可变长关键字参数**kwargs
*和**,也可以在函数调用的时候使用,称之为解包裹(unpacking)
注意:所有位置参数必须出现在默认参数前,包括函数定义和调用。有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序的。
函数返回值:
- 单返回值
- 多返回值:元组
def record_test(str="hello"):
print(str)
record_test() # 使用默认参数hello 输出hello
record_test(str="world") # 关键字参数 输出world
# 函数参数:默认参数,可变参数
def record_info(name, age, *args, **kwargs):
print(name, age) # 位置参数 输出Tom 13
print(args) # 可变长位置参数 输出(190, 32)
print(kwargs) # 可变长关键字参数 输出{'city': 'shenzhen', 'isMale': False}
record_info("Tom", 13, 190, 32, city="shenzhen", isMale=False)
函数的参数可接受另外一个函数,返回值也可以返回另外一个函数。
def foo():
print("foo")
def ff(func):
print("ff")
return func
ret_func = ff(foo) # 输出ff
ret_func() # 输出foo
匿名函数
- 形式:lambda
- lambda最好不要用于复杂的逻辑,可读性不好
- lambda表达式中的输入参数是一个自由变量
- 在运行时邦定值,而不是定义时就绑定:如果想让某个匿名函数在定义时就捕获到值,可以将那个参数值定义成默认参数。
# 匿名函数
lambda x: int(x)
# 上面的匿名函数等价于
def ret_int(item):
return int(item)
num_list = [1, "99", "77", 38]
num_list.sort(key=lambda x: int(x))
print(num_list) # 输出[1, 38, '77', '99']
高阶函数
1、map()
map() 会根据提供的函数对指定序列做映射。
第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
map_obj = map(lambda x: x**2, [10, 20, 30])
# 输出<map object at 0x0000000002880A58> [100, 400, 900]
print(map_obj, list(map_obj))
2、reduce()
reduce() 函数会对参数序列中元素进行累积。
函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。
import functools
sum = functools.reduce(lambda x, y: x+y, [1, 4, 5, 6])
print(sum) # 输出16
3、filter()
filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。
该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判断,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。
filter_obj = filter(lambda x: x % 2 == 0, [2, 4, 3, 2, 5, 3, 9, 7])
# 输出<filter object at 0x0000000002880A90> [2, 4, 2]
print(filter_obj, list(filter_obj))
函数变量作用域: LEGB 原则
locals(本地作用域)->enclosing function(闭包)->globals(全局作用域)->builtins(内置作用域)
当在函数中使用未确定的变量名时,Python 搜索 4 个作用域:本地作用域(L),之后是上一层嵌套结构中 def 或 lambda 的本地作用域(E),之后是全局作用域(G),最后是内置作用域(B)。按LEGB原则查找到则停止。如果没有找到则报错。
装饰器
一个装饰器就是一个函数,它接受一个函数作为参数并返回一个新的函数。
装饰器函数在被装饰的函数定义后立即执行。被装饰的函数只有在明确调用时才运行。
普通装饰器:
# 普通装饰器
def decorate(func):
print("decorate is running!")
def inner():
print("====inner===")
# 返回的函数被替换了
return inner
@decorate
def foo():
print("==foo==")
# foo()函数定义后执行装饰器decorate函数,输出decorate is running!
foo() #被装饰的函数只有在明确调用时才运行 输出====inner===, # 返回的函数被替换了
带参数的装饰器
import time
def record_time(func):
def inner(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs)
end_time = time.time()
print("%s函数运行了%f秒" % (func.__name__, end_time-start_time))
return inner
@record_time
def foo1():
print("foo1")
foo1() # 输出foo1 foo1函数运行了0.000500秒
def decorator1(func):
def inner(*args):
func(*args) # foo2 (10, 30, 'mm')
print("====decorator===", args) # ====decorator=== (10, 30, 'mm')
return inner
@decorator1
def foo2(*args):
print("foo2", args)
foo2(10, 30, "mm") # 输出foo2 (10, 30, 'mm') ====decorator=== (10, 30, 'mm')
import time
def record_time(func):
def inner(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs)
end_time = time.time()
print("%s函数运行了%f秒" % (func.__name__, end_time-start_time))
return inner
@record_time
def foo1():
print("foo1")
foo1() # 输出foo1 foo1函数运行了0.000500秒
def decorator1(func):
def inner(*args):
func(*args)
print("====decorator===", args)
return inner
@decorator1
def foo2(a):
print("foo2")
foo2(10) #输出foo2 ====decorator=== (10,)