python函数高级

函数是Python内建支持的一种封装,通过把大段代码拆成函数,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程程序设计的基本单元。

  • 变量可以指向函数,故可以将函数赋值给变量。
# 函数名赋值给变量
def func():
    print("hello world!")
    
new_func = func
new_func()

1. 高阶函数

一个函数接受另一个函数作为参数或者返回一个函数,即为高阶函数。

# 高阶函数
def test(func):
    x = 5
    print("hello world!")
    return func(x)

def num(x):
    return x ** 2

result = test(num)  # 接受一个函数作为参数
print(result)

2. 内置高阶函数

2.1 map函数
  • map(func, *iterables) --> map object
  • 接受一个函数和若干个可迭代对象作为参数,将函数依次作用于可迭代对象的每个元素,并将结果作为一个Iterator返回。
# map()h=函数
def square(num):
    return num ** 2

number = [1, 2, 3, 4]
result = map(square, number) 

print(type(result), result)
print(list(result))

# 执行结果
<class 'map'> <map object at 0x1053e5e48>
[1, 4, 9, 16]
2.2 reduce函数
  • python3中reduce函数已从全局名字空间中剔除。在functools模块中,from functools import reduce
  • reduce(function, sequence[, initial]) -> value
  • 接受一个函数和序列类型数据,该函数接受两个参数,该函数将序列的前两个元素作为函数参数执行,再将结果与后面元素依次做累积计算。
# reduce()函数
from functools import reduce

def multi(x, y ):
    return x * y

number = [1, 2, 3, 4, 5]
result = reduce(multi, number)
print(result)

# 执行结果
120
2.3 filter函数
  • filter函数用于过滤元素
  • filter(function or None, iterable) --> filter object
  • 接受一个函数和一个可迭代对象,将函数作用于每一个元素,根据结果为True或False决定是否保留元素,返回值为迭代器
# filter()函数:用于过滤元素

def odd(num):
    return num % 2

num = list(range(20))
result = filter(odd, num)
print(list(result))

# 执行结果
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
2.4 sorted函数
  • sorted函数用来对数据排序,也是一个高阶函数,不太明显。
  • sorted(iterable, key=None, reverse=False)
  • key可以接受一个函数作为排序依据,按函数执行结果排序后再返回原始元素排序。
# sorted()函数:排序
number = [-5, 9, 3, 27, -10]
m = sorted(number, key=abs)

print(m)

# 执行结果
[3, -5, 9, -10, 27]

3. 闭包

  • 一个函数返回一个内部函数,其内部函数引用了外部函数的相关参数和变量,则返回的内部函数及变量称为闭包。
  • 返回的函数并非立刻执行,当调用的时候才执行,延时执行
  • 特点是:引用外部参数和变量,即使外部函数结束(生成闭包的环境释放),该变量或参数仍然存在于闭包里面。
# 闭包
def make_func(name):
    
    def func():
        print("my name is %s." % name)
    
    return func

new_func = make_func("fengdi")
new_func()
  • 闭包无法修改外部函数的局部变量(若要修改,需使用nonlocal关键字声明)
  • 但可以修改外部函数中为可变类型的变量,比如列表
  • 尽量不要在闭包内引用循环变量或后续会发生变化的变量。若要使用循环变量,则要将函数参数绑定到循环变量的当前值。
# 闭包不要引用循环变量或后续会发生变化的变量
def count():
    fs = []
    for i in range(1, 4):
        def f():
             return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()
print(f1())
print(f2())
print(f3())

def count():
    fs = []
    for i in range(1, 4):
        def f(i=i):
             return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count()
print(f1())
print(f2())
print(f3())

# 执行结果 
9 
9 
9 
1 
4 
9

4. 装饰器

  • 装饰器:本质上是一个高阶函数,接受被装饰的函数为参数,返回一个包装后的函数,通过闭包实现。
  • 装饰器可在不改变原有函数的定义和调用形式来给原函数增加新的功能。

python实现装饰器有两种方式:① func = decorator(func)方式 ② @语法糖形式

# 装饰器:func = decorator(func)方式
def wrapper(func):
    def inner():
        print("------新功能添加------")
        func()
    
    return inner

def info():
    print("hello world!")
    
info = wrapper(info)   # 对Info函数进行装饰,添加功能,此时Info函数指向一个新的函数inner
info()

# 装饰器:@语法糖形式
def wrapper(func):
    def inner():
        print("------新功能添加------")
        func()
    
    return inner

@wrapper
def info():
    print("hello world!")
    
info()

# 执行结果
------新功能添加------
hello world!
------新功能添加------
hello world!
  • 程序从上往下执行过程中遇到装饰器就开始装饰,而不是调用函数时才开始装饰。
# 装饰器装饰时间
def wrapper(func):
    print("------装饰器开始装饰------")
    def inner():
        print("------新功能添加------")
        func()
    
    return inner

@wrapper
def info():
    print("hello world!")
    
# 执行结果
------装饰器开始装饰------
  • 当被装饰的函数有参数或者返回值时,返回的内部函数也拥有参数及返回值(return func())
# 装饰有返回值函数
def wrapper(func):
    def inner():
        print("------新功能添加------")
        return func()  # 被装饰函数具有返回值,则内部函数也应有返回值
    
    return inner

@wrapper
def info():
    return "hello world!!!"

result = info()
print(result)

# 执行结果 
------新功能添加------ 
hello world!!! 
# 装饰有参数函数
def wrapper(func):
    def inner(name):
        print("------新功能添加------")
        return func(name)  # 被装饰函数具有参数,内部函数也应有参数
    
    return inner

@wrapper
def info(name):
    return "my name is %s." % name

result = info("fengdi")
print(result)

# 执行结果 
------新功能添加------ 
my name is fengdi. 
  • 通用装饰器:不管被装饰的函数有无参数、有无返回值均适用
# 通用装饰器:有无参数,有无返回值,任意个参数均可
def wrapper(func):
    def inner(*args, **kwargs):
        print("------新功能添加------")
        return func(*args, **kwargs)  # 被装饰函数具有参数,内部函数也应有参数
    
    return inner
  • 装饰器可定义多个,装饰时离函数最近的装饰器先被调用进行装饰,函数执行时从上往下开始执行。
# 多个装饰器装饰一个函数
def wrapper1(func):
    print("------装饰器wrapper1开始装饰------")
    def inner():
        print("------新功能1添加------")
        return func()  # 被装饰函数具有参数,内部函数也应有参数
    
    return inner

def wrapper2(func):
    print("------装饰器wrapper2开始装饰------")
    def inner():
        print("------新功能2添加------")
        return func()  # 被装饰函数具有参数,内部函数也应有参数
    
    return inner

@wrapper1
@wrapper2
def info():
    print("hello world!")
    
print("-" * 40)
info()

# 执行结果
------装饰器wrapper2开始装饰------
------装饰器wrapper1开始装饰------
----------------------------------------
------新功能1添加------
------新功能2添加------
hello world!
  • 带参数的装饰器

    • 装饰器本身需要传入参数时,可在外部在嵌套一个函数接收参数,返回装饰器
    • 带参数一般是用来根据参数返回不同的装饰器
# 有参数的装饰器
def outer(num):
    def wrapper(func):
        def inner():
            print("---------权限验证%d---------" % num)
            func()
        return inner
    return wrapper

@outer(1)
def test1():
    print("--------test1---------")

@outer(2)
def test2():
    print("--------test2---------")
    
test1()
test2()

# 执行结果
---------权限验证1---------
--------test1---------
---------权限验证2---------
--------test2---------

5. 偏函数

  • 偏函数接受一个函数作为参数(将该函数的某些参数固定住),返回一个新的函数
  • 当函数参数太多,需要固定某些参数时,可使用partial创建一个新的函数,并将某些参数值固定
from functools import partial  

def multi(x, y): 
    return x * y  

double = partial(multi, y=2) 
print(double(2)) 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,825评论 4 377
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,887评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,425评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,801评论 0 224
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,252评论 3 299
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,089评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,216评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 31,005评论 0 215
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,747评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,883评论 2 255
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,354评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,694评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,406评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,222评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,242评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,017评论 2 281