概述
定义一个函数
你可以定义一个由自己想要功能的函数,以下是简单的规则:
函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
函数内容以冒号 : 起始,并且缩进。
return [表达式] 结束函数,选择性地返回一个值给调用方,不带表达式的 return 相当于返回 None。

def 函数名(参数列表):
函数体
定义一个简单函数
def fn() :
print('这是我的第一个函数!')
print('hello')
print('今天天气真不错!')
调用函数
fn()

函数传参
# 求任意三个数的乘积
def mul(a,b,c):
print(a*b*c)
# 调用
mul(1,2,3)

# 根据不同的用户名显示不同的欢迎信息
def welcome(username):
print('欢迎',username,'光临')
# 调用
welcome('孙悟空')

为函数参数设置默认值
# 定义一个函数
# 定义形参时,可以为形参指定默认值
# 指定了默认值以后,如果用户传递了参数则默认值没有任何作用
# 如果用户没有传递,则默认值就会生效
def fn(a = 5 , b = 10 , c = 20):
print('a =',a)
print('b =',b)
print('c =',c)
# 调用
fn(1 , 2 , 3)
fn(1 , 2)
fn()

实参的传递方式
# 位置参数
# 位置参数就是将对应位置的实参复制给对应位置的形参
# 第一个实参赋值给第一个形参,第二个实参赋值给第二个形参 。。。
fn(1 , 2 , 3)

关键字参数
# 关键字参数,可以不按照形参定义的顺序去传递,而直接根据参数名去传递参数
fn(b=1 , c=2 , a=3)

def fn4(a):
# 在函数中对形参进行重新赋值,不会影响其他的变量
# a = 20
# a是一个列表,尝试修改列表中的元素
# 如果形参执行的是一个对象,当我们通过形参去修改对象时
# 会影响到所有指向该对象的变量
a[0] = 30
print('a =',a,id(a))
c = 10
c = [1,2,3]
fn4(c)
fn4(c.copy())
fn4(c[:])

不定长的参数
# 定义一个函数,可以求任意个数字的和
def sum(*nums):
# 定义一个变量,来保存结果
result = 0
# 遍历元组,并将元组中的数进行累加
for n in nums :
result += n
print(result)
# 调用函数
sum(123,456,789,10,20,30,40)
sum(123,456)

# 在定义函数时,可以在形参前边加上一个*,这样这个形参将会获取到所有的实参
# 它将会将所有的实参保存到一个元组中
# a,b,*c = (1,2,3,4,5,6)
# *a会接受所有的位置实参,并且会将这些实参统一保存到一个元组中(装包)
def fn(*a):
print("a =",a,type(a))
# 调用
fn(1,2,3,4,5)

带星号的形参只能有一个
带星号的参数,可以和其他参数配合使用
# 第一个参数给a,第二个参数给b,剩下的都保存到c的元组中
def fn2(a, b, *c):
print('a =', a)
print('b =', b)
print('c =', c)
# 调用函数
fn2(2, 3, 4, 5, 6)

可变参数不是必须写在最后,但是注意,带*的参数后的所有参数,必须以关键字参数的形式传递
# 可变参数不是必须写在最后,但是注意,带*的参数后的所有参数,必须以关键字参数的形式传递
# 第一个参数给a,剩下的位置参数给b的元组,c必须使用关键字参数
def fn2(a, *b, c):
print('a =', a)
print('b =', b)
print('c =', c)
fn2(1, 2, 3, 4, c=2)
# 所有的位置参数都给a,b和c必须使用关键字参数
print("第一个参数有*")
def fn2(*a, b, c):
print('a =', a)
print('b =', b)
print('c =', c)
fn2(1, 2, 3, b=2, c=1)
# 如果在形参的开头直接写一个*,则要求我们的所有的参数必须以关键字参数的形式传递
print("形参的开头直接写一个*")
def fn2(*, a, b, c):
print('a =', a)
print('b =', b)
print('c =', c)
fn2(a=3,b=4,c=5)
print("**形参")
# **形参可以接收其他的关键字参数,它会将这些参数统一保存到一个字典中
# 字典的key就是参数的名字,字典的value就是参数的值
# **形参只能有一个,并且必须写在所有参数的最后
def fn3(b, c, **a):
print('a =', a, type(a))
print('b =', b)
print('c =', c)
fn3(b=1,d=2,c=3,e=10,f=20)

参数的解包(拆包)
def fn4(a, b, c):
print('a =', a)
print('b =', b)
print('c =', c)
# 创建一个元组
t = (10, 20, 30)
# 传递实参时,也可以在序列类型的参数前添加星号,这样他会自动将序列中的元素依次作为参数传递
# 这里要求序列中元素的个数必须和形参的个数的一致
fn4(*t)
# 创建一个字典
d = {'a': 100, 'b': 200, 'c': 300}
# 通过 **来对一个字典进行解包操作
fn4(**d)

返回值
返回值就是函数执行以后返回的结果
可以通过 return 来指定函数的返回值
可以之间使用函数的返回值,也可以通过一个变量来接收函数的返回值
def sum(*nums):
# 定义一个变量,来保存结果
result = 0
# 遍历元组,并将元组中的数进行累加
for n in nums:
result += n
return result
print(sum(123, 456, 789))

return 后边跟什么值,函数就会返回什么值,return 后边可以跟任意的对象,返回值甚至可以是一个函数
def fn():
# return 'Hello'
# return [1,2,3]
# return {'k':'v'}
def fn2():
print('hello')
return fn2 # 返回值也可以是一个函数
r = fn() # 这个函数的执行结果就是它的返回值
# r()
print(fn())
print(r)

如果仅仅写一个return 或者 不写return,则相当于return None
def fn2():
a = 10
return
print(fn2())

在函数中,return后的代码都不会执行,return 一旦执行函数自动结束
def fn3():
print('hello')
return
print('abc')
r = fn3()
print(r)

def fn4():
for i in range(5):
if i == 3:
# break 用来退出当前循环
# continue 用来跳过当次循环
return # return 用来结束函数
print(i)
print('循环执行完毕!')
fn4()

fn5 和 fn5()的区别
def fn5():
return 10
print(fn5) # fn5是函数对象,打印fn5实际是在打印函数对象 <function fn5 at 0x05771BB8>
print(fn5()) # fn5()是在调用函数,打印fn5()实际上是在打印fn5()函数的返回值 10

文档字符串
# help()是Python中的内置函数
# 通过help()函数可以查询python中的函数的用法
# 语法:help(函数对象)
# help(print) # 获取print()函数的使用说明
# 文档字符串(doc str)
# 在定义函数时,可以在函数内部编写文档字符串,文档字符串就是函数的说明
# 当我们编写了文档字符串时,就可以通过help()函数来查看函数的说明
# 文档字符串非常简单,其实直接在函数的第一行写一个字符串就是文档字符串
def fn(a: int, b: bool, c: str = 'hello') -> int:
'''
这是一个文档字符串的示例
函数的作用:。。。。。
函数的参数:
a,作用,类型,默认值。。。。
b,作用,类型,默认值。。。。
c,作用,类型,默认值。。。。
'''
return 10
help(fn)

作用域
作用域指的是变量生效的区域
def fn():
a = 10 # a定义在了函数内部,所以他的作用域就是函数内部,函数外部无法访问
print('函数内部:','a =',a)
print('函数内部:','b =',b)
fn()

高阶函数
只要满足下面的任意一个条件就是高阶函数
1、一个函数的函数名作为参数传给另外一个函数
2、一个函数返回值(return)为另外一个函数(返回为自己,则为递归)
高阶函数:一个函数的函数名作为参数传给另外一个函数
def func():
print("定义一个普通函数")
def high_level(func):
print("定义一个高阶函数")
# 在函数内部,通过传入的函数参数调用
func()
high_level(func)

高阶函数:一个函数返回值(return)为另外一个函数
def func():
print("定义一个普通函数")
def high_level(func):
print("定义一个高阶函数")
return func
# return func() 这个是直接返回函数调用,递归函数就是如此
res = high_level(func)
# 高阶函数返回函数之后在调用func函数
res()
# 结果

闭包
将函数作为返回值返回,也是一种高阶函数
这种高阶函数我们也称为叫做闭包,通过闭包可以创建一些只有当前函数能访问的变量
可以将一些私有的数据藏到的闭包中
def fn():
a = 10
# 函数内部再定义一个函数
def inner():
print('我是fn2' , a)
# 将内部函数 inner作为返回值返回
return inner
# r是一个函数,是调用fn()后返回的函数
# 这个函数实在fn()内部定义,并不是全局函数
# 所以这个函数总是能访问到fn()函数内的变量
a=100
r = fn()
r()
形成闭包的要件
① 函数嵌套
② 将内部函数作为返回值返回
③ 内部函数必须要使用到外部函数的变量
def make_averager():
# 创建一个列表,用来保存数值
nums = []
# 创建一个函数,用来计算平均值
def averager(n) :
# 将n添加到列表中
nums.append(n)
# 求平均值
return sum(nums)/len(nums)
return averager
averager = make_averager()
print(averager(10))
print(averager(20))
print(averager(30))
print(averager(40))

装饰器
相当于高阶函数,根据现有的函数,来创建一个新的函数
希望函数可以在计算前,打印开始计算,计算结束后打印计算完毕
我们可以直接通过修改函数中的代码来完成这个需求,但是会产生以下一些问题
① 如果要修改的函数过多,修改起来会比较麻烦
② 并且不方便后期的维护
③ 并且这样做会违反开闭原则(OCP)
程序的设计,要求开发对程序的扩展,要关闭对程序的修改
def add(a , b):
'''
求任意两个数的和
'''
r = a + b
return r
# 只需要根据现有的函数,来创建一个新的函数
def fn2(a, b):
print('函数开始执行~~~')
print(add(a, b))
print('函数执行结束~~~')

def new_add(a, b):
print('计算开始~~~')
r = add(a, b)
print('计算结束~~~')
return r
r = new_add(111,222)
print(r)

上边的方式,已经可以在不修改源代码的情况下对函数进行扩展了
但是,这种方式要求我们每扩展一个函数就要手动创建一个新的函数,实在是太麻烦了
为了解决这个问题,我们创建一个函数,让这个函数可以自动的帮助我们生产函数
def add(a, b):
'''
求任意两个数的和
'''
r = a + b
return r
def mul(a, b):
'''
求任意两个数的积
'''
r = a * b
return r
def begin_end(old):
'''
用来对其他函数进行扩展,使其他函数可以在执行前打印开始执行,执行后打印执行结束
参数:
old 要扩展的函数对象
'''
# 创建一个新函数
def new_function(*args, **kwargs):
print('开始执行~~~~')
# 调用被扩展的函数,直接把要扩展的函数当参数传进来就行了
result = old(*args, **kwargs)
print('执行结束~~~~')
# 返回函数的执行结果
return result
# 返回新函数
return new_function
f2 = begin_end(add)
f3 = begin_end(mul)
s = f2(123,456)
r = f3(123,456)
print(r)
print(s)

装饰器的语法糖@
装饰器的语法使用 @decorator_name 来应用在函数或方法上来装饰当前的函数
可以同时为一个函数指定多个装饰器,这样函数将会安装从内向外的顺序被装饰
相当于把新函数作为参数传入@的函数里面。
def fn3(old):
'''
用来对其他函数进行扩展,使其他函数可以在执行前打印开始执行,执行后打印执行结束
参数:
old 要扩展的函数对象
'''
# 创建一个新函数
def new_function(*args, **kwargs):
print('fn3装饰~开始执行~~~~')
# 调用被扩展的函数
result = old(*args, **kwargs)
print('fn3装饰~执行结束~~~~')
# 返回函数的执行结果
return result
# 返回新函数
return new_function
# 相当于把 say_hello()函数作为参数传入fn3()函数
def say_hello():
print('大家好~~~')
cms = fn3(say_hello)
cms()

def fn3(old):
'''
用来对其他函数进行扩展,使其他函数可以在执行前打印开始执行,执行后打印执行结束
参数:
old 要扩展的函数对象
'''
# 创建一个新函数
def new_function(*args, **kwargs):
print('fn3装饰~开始执行~~~~')
# 调用被扩展的函数
result = old(*args, **kwargs)
print('fn3装饰~执行结束~~~~')
# 返回函数的执行结果
return result
# 返回新函数
return new_function
# 相当于把 say_hello()函数作为参数传入fn3()函数
@fn3
def say_hello():
print('大家好~~~')
say_hello()

语法糖是支持多层装饰的,写法上从下到上,函数嵌套从内到外对应
def begin_end(old):
'''
用来对其他函数进行扩展,使其他函数可以在执行前打印开始执行,执行后打印执行结束
参数:
old 要扩展的函数对象
'''
# 创建一个新函数
def new_function(*args, **kwargs):
print('开始执行~~~~')
# 调用被扩展的函数,直接把要扩展的函数当参数传进来就行了
result = old(*args, **kwargs)
print('执行结束~~~~')
# 返回函数的执行结果
return result
# 返回新函数
return new_function
def fn3(old):
'''
用来对其他函数进行扩展,使其他函数可以在执行前打印开始执行,执行后打印执行结束
参数:
old 要扩展的函数对象
'''
# 创建一个新函数
def new_function(*args, **kwargs):
print('fn3装饰~开始执行~~~~')
# 调用被扩展的函数
result = old(*args, **kwargs)
print('fn3装饰~执行结束~~~~')
# 返回函数的执行结果
return result
# 返回新函数
return new_function
# 相当于把 say_hello()函数作为参数传入fn3()函数
@fn3
@begin_end
def say_hello():
print('大家好~~~')
say_hello()

def begin_end(old):
'''
用来对其他函数进行扩展,使其他函数可以在执行前打印开始执行,执行后打印执行结束
参数:
old 要扩展的函数对象
'''
# 创建一个新函数
def new_function(*args, **kwargs):
print('开始执行~~~~')
# 调用被扩展的函数,直接把要扩展的函数当参数传进来就行了
result = old(*args, **kwargs)
print('执行结束~~~~')
# 返回函数的执行结果
return result
# 返回新函数
return new_function
def fn3(old):
'''
用来对其他函数进行扩展,使其他函数可以在执行前打印开始执行,执行后打印执行结束
参数:
old 要扩展的函数对象
'''
# 创建一个新函数
def new_function(*args, **kwargs):
print('fn3装饰~开始执行~~~~')
# 调用被扩展的函数
result = old(*args, **kwargs)
print('fn3装饰~执行结束~~~~')
# 返回函数的执行结果
return result
# 返回新函数
return new_function
# 相当于把 say_hello()函数作为参数传入fn3()函数
@begin_end
@fn3
def say_hello():
print('大家好~~~')
say_hello()

def begin_end(old):
'''
用来对其他函数进行扩展,使其他函数可以在执行前打印开始执行,执行后打印执行结束
参数:
old 要扩展的函数对象
'''
# 创建一个新函数
def new_function(*args, **kwargs):
print('开始执行~~~~')
# 调用被扩展的函数,直接把要扩展的函数当参数传进来就行了
result = old(*args, **kwargs)
print('执行结束~~~~')
# 返回函数的执行结果
return result
# 返回新函数
return new_function
def fn3(old):
'''
用来对其他函数进行扩展,使其他函数可以在执行前打印开始执行,执行后打印执行结束
参数:
old 要扩展的函数对象
'''
# 创建一个新函数
def new_function(*args, **kwargs):
print('fn3装饰~开始执行~~~~')
# 调用被扩展的函数
result = old(*args, **kwargs)
print('fn3装饰~执行结束~~~~')
# 返回函数的执行结果
return result
# 返回新函数
return new_function
# 相当于把 say_hello()函数作为参数传入fn3()函数
@begin_end
@fn3
@begin_end
def say_hello():
print('大家好~~~')
say_hello()

1618

被折叠的 条评论
为什么被折叠?



