Python学习(四)

高阶函数

把函数作为参数传入,这样的函数称为高阶函数

from math import sqrt

def test(x, *func):
    ret = list(f(x) for f in func)
    return ret

print(test(4, abs, sqrt))       # [4, 2.0]

map函数

map函数接收两个参数,第一个是一个函数,第二个是Iterable,map将传入的函数依次作用到Iterable中的每个元素,并把结果作为新的Iterator返回

# 将名字变为首字母大写,其他小写
def test(elem):
return elem.capitalize()

print(list(map(test, ['adam', 'LISA', 'barT'])))        # ['Adam', 'Lisa', 'Bart']

reduce函数

reduce函数接收两个参数,第一个是一个函数,第二个是一个序列,reduce将传入的函数依次作用到Iterable中的每个元素,并把每一个元素的结果与下一个元素作累积计算

from functools import reduce

def str2int(s):
    def char2num(c):
        # 根据dict中的key来获取value
        return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[c]

    def f(x, y):
        return x * 10 + y

    return reduce(f, map(char2num, s))


print(str2int("13579"))             # 13579
print(type(str2int("13579")))       # <class 'int'>

上面是我们自己写的一个str转int的函数,虽然系统给我们提供了。我们还可以写一个str转float的函数来加强reduce与map的理解

def str2float(s):
    # 获取小数点的位置
    point = s.index(".")
    # 整数部分
    num1 = map(int, s[:point])
    # 小数部分
    num2 = map(int, s[point + 1:])
    # 算出小数有多少位
    num3 = 1 / 10 ** len(s[point + 1:])

    def f(x, y):
        return x * 10 + y

    return reduce(f, num1) + reduce(f, num2) * num3


print(str2float("126.789"))                 # 126.789
print(type(str2float("126.789")))           # <class 'float'>

filter函数

filter()也接收一个函数和一个序列,把传入的函数依次作用于每一个序列的元素,然后根据返回值是True还是False来决定保留还是丢弃该元素。filter()函数返回的是一个Iterator

def func(elem):
return elem % 2 == 0


print(list(filter(func, list(range(1, 11)))))       # [2, 4, 6, 8, 10]

sorted函数

sorted()可以对一个序列进行排序,也可以接收一个key来实现自定义的排序

l = [36, 5, -12, 9, -21]
print(sorted(l))                            # [-21, -12, 5, 9, 36]  从小到大
print(sorted(l, reverse=True))            # [36, 9, 5, -12, -21]    从大到小
print(sorted(l, key=abs))                  # [5, 9, -12, -21, 36]   按绝对值的大小排序

对字符串进行排序。对字符串排序是按照ASCII大小比较的,由于'Z'<'a',大写字母Z会排在小写字母a的前面,所以可以过字符串的lower方法将先把字符串都变成小写(也可以都变成大写),再比较

L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88), ('Zoo', 40)]
def by_name(item):
    return item[0].lower()
print(sorted(L, key=by_name))       # [('adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88), ('Zoo', 40)]

返回函数

上面学习了将函数作为参数的高阶函数,也可以把函数作为结果值返回

def test(*args):
    def f():
        ret = 0
        for item in args:
            ret += item
        return ret
    return f
result = test(1, 3, 5, 7, 9)
# 返回回来的是一个函数,必须调用才能获取到返回值
print(result())         # 25
print(result)           # <function test.<locals>.f at 0x101a7ac80>

我们在函数test中定义了函数f,内部函数f可以引用外部函数test的的参数和局部变量;当函数test返回函数f时,相关参数和变量都保存在返回的函数中,这种称为闭包(Closure)。但这里有一个问题需要注意:

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

        fs.append(f)
    return fs
f1, f2, f3 = test2()
print(f1())     # 9
print(f2())     # 9
print(f3())     # 9

这里的结果为什么都是9?

原因在于返回的函数引用了变量i,但它并非立即执行,等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果都是9。

所以,返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量

若一定要引用循环变量怎么办呢?可以这样做:

def test3():
    fs = []

    def f(x):
        def g():
            return x * x

        return g

    for i in range(1, 4):
        fs.append(f(i))         # f(i)立即被执行,因此当前i的值被传入到f()函数中
    return fs
f4, f5, f6 = test3()
print(f4())         # 1
print(f5())         # 4
print(f6())         # 9

重新创建了一个函数,用该函数的参数与循环变量当前的值进行绑定,无论后绪循环变量如何变,已绑定的函数参数的值不变

匿名函数

结构:

lambda 参数名 : 表达式    或者  lambda : 表达式

如:

print(list(map(lambda x: x * x, [1, 2, 3])))        # [1, 4, 9]
def test(x, y):
    return lambda: x + y
print(test(1, 2)())                              # 3

装饰器

在代码运行期间动态增加功能的方式称之为装饰器(Decorator)

# 调用函数time时,输出log日志

import functools

def log(func):
    # 把原始函数的__name__等属性复制到wrapper()函数中,否则返回出去的__name__属性值为wrapper
    @functools.wraps(func)      
    def wrapper(*args, **kw):
        print("call %s():" % func.__name__)
        return func(*args, **kw)

    return wrapper
    
# 这里相当于执行:time = log(time)    
@log 
def time():
    print("2017-2-5")
       
time()                  # call time():  2017-2-5
print(time.__name__)      # time

自定义一个输出log文本的装饰器

def log2(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print("%s ,%s():" % (text, func.__name__))
            return func(*args, **kw)

        return wrapper

    return decorator

# 这里相当于执行:time2 = log("execute")(time2)
@log2("execute")   
def time2():
    print("2017-1-5")
    
time2()                 # execute ,time2(): 2017-1-5
print(time2.__name__)     # time2

首先执行的是log("execute"),返回decorator,再调用返回的函数,参数就是time2,返回值最终是wrapper函数

偏函数

在学习函数参数类型的时候,为了降低函数的调用难度,我们可以设置默认参数。而偏函数也可以做到。
偏函数的作用就是:把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单

def test(x, sqrt=2):
return x ** sqrt

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

推荐阅读更多精彩内容