Python

Python学习(四)

2017-02-05  本文已影响20人  BlainPeng

高阶函数

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

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
上一篇下一篇

猜你喜欢

热点阅读