Python函数式编程 学习记录

  最近写了js和C++,发现写脚本语言的爽快,数据初始化简便,一些地方不用太在意数据类型,python想用什么库直接pip就可以,简直不能再爽,所以写这篇来记录一些关于python的函数式编程。

  python内置map()与reduce()函数,与迭代器Iterator相关联,map(p1,p2),p1是函数,p2是数据,实现过程应该大概是迭代器指向p1,然后把p2的元素传到p1,假设p1=f(x),p2=[a,b,c,d,e,f],则调用方式为f(a),f(b)…,在python中,Iterator被称为惰性序列,看了介绍,惰性计算,大概意思就是把表达式,如f(a),这样的存到一个变量,而不是直接求出值,到使用的时候才求,而惰性序列就是包含惰性计算存储的序列。
例子来自:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014317852443934a86aa5bb5ea47fbbd5f35282b331335000

例子:

from functools import map
 def f(x):
     return x * x
r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]

  reduce的用法。reduce把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算。
例子字符串转换为数字:

from functools import reduce
def fn(x, y):
    return x * 10 + y

def char2num(s):
    digits = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
    return digits[s]

reduce(fn, map(char2num, '13579'))
13579

  看完后,让我想起了C++的 for_each,与iterator,于是写了个C++版本:

int strToint(string str) {
    auto start = str.begin();
    auto end = str.end();
    auto len = end - start;
    int temp = 0;
    for_each(start, end, [&](char tmp) {
        map<char, int> m;
        char flag = '0';
        len--;
        for (int i = 0; i <= 9; i++) {
            m[flag] = i;
            flag++;
        }
        temp += m[tmp];
        if (len != 0) {
            temp *= 10;
        }
    });
    return temp;
}

  Python内建的filter(),第一个参数是一个返回true或false,根据返回值是True还是False决定保留还是丢弃该元素。
  我自己觉得吧,在这方面,感觉使用C++的for_each自己实现比较方便,而python把他们分为各个函数,大概是因为返回的是一个iterator序列,便于处理,各个函数做自己的事,模块化。

  闭包:js中的一个非常重要的特性,在内部函数能访问其外部函数的作用域变量,函数,即使外部函数返回(调用完毕返回值),还是可以访问,在python里也一样,比如:

def count():
    val=[]
    for i in range(3):
        def f():
            return i*i
        val.append(f)
    return val

a=count()
for i in a:
    print(i())
4
4
4 

  在返回函数的时候,由于i外部变量,执行到最后i =2(range(3)<=>[0,3)),所以结果都是4,

  lambda函数,lambda 参数: 函数体 (感觉还是C++与js的写着舒服)

  装饰器,可以理解为在调用函数之前会执行的一个函数,例子:

import time , functools

def log(Text):
    #@functools.wraps(func)
    def callback(func):
        localtime=time.asctime()
        print(Text)
        print('当前时间为:%s,调用的函数是:%s'%(localtime,func.__name__))
        return func
    return callback

@log('Text:')
def m():
    print('this is a func')
m()
print(m)

  在函数上面加上@+函数名,就相当于把下面定义的函数当作参数导入@的函数,如上,就是把函数m()当作参数传入log(‘Text’)里,log(‘Text’)返回的是callback函数,相当于调用了callback(m),过程如下

#相当于生成一个与m()函数名字相同的变量,把m函数传入,最后返回m函数的地址,保证函数最后没运行错
m=log('Text')(m)

  还有一种情况,也就是闭包的时候,例子如下:

import time , functools

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

@log('Text:')
def m():
    print('this is a func')

m()
print(m.__name__)
结果:
Text: m():
this is a func
wrapper

  原因是在调用decorator的时候,返回的是wrapper的对象,所以m=wrapper,因为在函数里面闭包,参数仍然是m()函数,所以输出name还是m,但是在外面,m的name就变成了wrapper,这意味着我们可以通过m调用wrapper函数么?并不,因为再次调用m()还会重复上面的步骤,函数调用结果没变,但是函数的__name__属性被改变,会影响我们在一些地方的操作,如通过函数名调用函数之类的

猜你喜欢

转载自blog.csdn.net/qq_21049875/article/details/79035448