04月04, 2019

Python学习中的一些小技巧

本篇主要通过使用示例介绍python学习中遇到的一些小技巧的。

1、生成器

生成器其实就是一个边循环边计算的机制,这样说可能不大容易理解,我们先写一个简单的例子(生成1到10 的平方数集合): 一般情况可以这样实现:

for n in range(1,11):
    print(n*n)

如果将这一功能改造成生成器:

g=(x*x for x in range(1,11))
print(next(g))
print(next(g))
print(next(g))
print(next(g))

输出结果:

1
4
9
16

不难发现,执行一次next(g),输出依次输出平方数结果,但是这样的输出比较恶心(如此多的的next()),一般可以迭代输出(比如for)

for n in g:
    print(n)

接下来我们通过一个生成斐波那契数列的例子了解下生成器的另一种形式:

不用生成器的斐波那契函数我们可能这样写:

def fib(n):
    a,b,c=0,1,0
    while(c<n):
        print(b,end=" ")
        a,b=b,a+b
        c+=1;
    return b;

#函数调用
fib(5)

输出结果:

1 1 2 3 5 

使用生成器的写法:

def fib2(n):
    a,b,c=0,1,0
    while(c<n):
        yield b
        a,b=b,a+b
        c+=1;
    return b;

#打印结果
f=fib2(5)
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))

输出结果:

1 1 2 3 5 

通过比较我们可以看到两者的区别就是把print(b,end=" ")改成 yield b,其实这就是一个生成器(如果一个函数中包含yield关键字,这个函数就是一个生成器)。与普通函数不一样的是, 生成器是在调用next()的时候执行,在执行过程中遇到yield关键字就会返回,然后下一个next()再从上次返回的地方继续执行,遇到yield再返回...如此往复直到结束

比如,

  • 第一次执行next(f),程序走到yield b,此时 a=0,b=1,返回b=1
  • 第二次从上次返回地方接着执行,a=b=1,b=a+b=0+1=1,c=1,while判断后 又到yield,返回b=1
  • 第三次 a=b=1,b=a+b=1+1=2,c=2,遇到yield返回b=2

  • ....

看到这是否已经明白了生成器的使用,有兴趣的可以使用生成器写个打印杨辉三角的程序。

[1],
[1, 1],
[1, 2, 1],
[1, 3, 3, 1],
[1, 4, 6, 4, 1],
[1, 5, 10, 10, 5, 1],
[1, 6, 15, 20, 15, 6, 1],
[1, 7, 21, 35, 35, 21, 7, 1],
[1, 8, 28, 56, 70, 56, 28, 8, 1],
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]

先自己想想在看答案~~

杨辉三角.py

2、map()/reduce()

前言

map/reduce的概念其实很早就已经提出来了,简单的说,map()函数主要是生成中间key/value键值对,reduce()函数将中间key/value键值对进行计算并产生新的几组数据,有兴趣的可以详细阅读下之前的两篇关于mapReduce的文章:

《MapReduce:大型集群上的简化数据处理》 论文详解(上)

《MapReduce:大型集群上的简化数据处理》 论文详解(下)

下面介绍下python的map和reduce函数

map():

map()函数接受两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。这里强调一下Iterable和Iterator的区别:

  • Iterable:可以通过for循环遍历,比如:str、list、dict
  • Iterator:可以通过next()进行遍历

Iterable变成Iterator可以使用iter()函数

举个栗子:计算一个序列中所有元素的平方f(n)=n^2,

def f(n):
    return n*n;

#调用
l=range(1,11);
l=map(f,l)
print(list(l))  #Iterator 可以用list函数直接遍历

输出结果:

1 4 9 16 25 36 49 64 81 100 

reduce()

reduce函数也接收两个参数,函数和Iterable,但是作为参数的函数必须有两个参数。与map函数不同的是,reduce函数是把结果与序列中的下一个元素继续进行计算:

reduce(f,[x1,x2,x3])=f(f(x1,x2),x3)

举个栗子:

def f(x,y):
    return x+y;

#调用
#需要引入函数工具类库
from functools import reduce
l=range(1,11);
sum=reduce(f,l)
print(sum)

输出结果:

55

其实map()和reduce()一起用效果更佳,举个栗子,将字符串转为数字:

def str2Int(x,y):
    return x*10+y;
#调用
from functools import reduce
sum=reduce(str2Int,map(int,"9999")) #int()函数是将字符转为整数
print(sum+1)

输出结果

10000

这个程序只是举个栗子说明map和reduce函数之间的协调处理,其实这个功能借助lambda能够更简单的实现:

sum=reduce(lambda x,y:x*10+y,map(int,"9999"))
print(sum+1)

其实如果只看功能,最简单的方式是。。sum=int("9999")+1,再次强调这样实现只是为了介绍map()函数和reduec()函数的协同处理任务的能力。

有兴趣的可以写个转换程序:将字符串“999.999”转为浮点类型999.999,不准使用Python的内建函数,比如float(),最好用map()+reduce()实现

先自己想想在看答案~~

参考:_str_2_float_.py

扫鸭扫鸭,求关注

alt

本文链接:http://blog.keepting.cn/blog//post/python_function.html

-- EOF --

Comments