一、难点和疑惑
今天接触了reduce和filter这两个之前从没接触过的内置函数,在翻看文档时对filter的使用基本上没有问题了,但是卡在了reduce上,对reduce的用法不是很熟悉,很多例子也写不来,所以一直在反复看reduce以及相关的练习题。
二、python基础
2.1 高阶函数
- map
1.map接受两个参数,一个是函数,一个是iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的iterable返回。
# -*- coding=utf-8 -*-
def func(x):
return x ** 2
res = map(func, [1, 2, 3, 4, 5])
print res
# [1, 4, 9, 16, 25]
map()
传入的第一个参数是f
,即函数对象本身。由于结果r
是一个Iterator
,Iterator
是惰性序列,因此通过list()
函数让它把整个序列都计算出来并返回一个list。
第一次接触map是在刷题的时候,那时候不知道怎么输入一个不定长数组,就问了我的学长,看了他的代码,硬是把格式记了下来。
data = map(int,raw_input().split())
当时大概也能知道其中的意义,通过现在的学习又把map重新学了一遍,原理搞懂了。
-
reduce()
函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。
# -*- coding=utf-8 -*- from functools import reduce def add(a, b): return a + b res = reduce(add, [1, 2, 3, 4, 5]) print res # 结果与sum([1,2,3,4,5])相同 ------------- # 但是如果要把序列[1, 3, 5, 7, 9]变换成整数13579,reduce就可以派上用场: # -*- coding=utf-8 -*- def func(a, b): return a * 10 + b res = reduce(func, [1, 2, 3, 4, 5]) print res
- 字符串转数字
# -*- coding=utf-8 -*- from functools import reduce digital = { str(i): i for i in xrange(10) } def func(a, b): return a * 10 + b def char_to_num(c): return digital[c] print reduce(func,map(char_to_num,'1456'))
-
reduce求积
def prod(L): def mul(a, b): return a * b return reduce(mul, L) print('3 * 5 * 7 * 9 =', prod([3, 5, 7, 9]))
2.2 filter
filter()
把传入的函数依次作用于每个元素,然后根据返回值是True
还是False
决定保留还是丢弃该元素。
案例1:在一个list中,删掉偶数,只保留奇数
def is_odd(num):
return num % 2 == 1
print filter(is_odd, [1, 2, 3, 4, 5, 6])
filter关键在于正确实现一个“筛选”函数。filter()
的作用是从一个序列中筛出符合条件的元素。由于filter()
使用了惰性计算,所以只有在取filter()
结果的时候,才会真正筛选并每次返回下一个筛出的元素。
2.3 sorted
sorted()
函数也是一个高阶函数,它还可以接收一个key
函数来实现自定义的排序
sorted([36, 5, -12, 9, -21], key=abs)
# 默认升序,要想降序可以加reverse=True
data = [2, 1, 5, 3, 6, 9, 4]
print sorted(data, reverse=True)
key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果进行排序
2.4 匿名函数
当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。
lambda x:x**2
关键字lambda
表示匿名函数,冒号前面的x
表示函数参数。匿名函数有个限制,就是只能有一个表达式,不用写return
,返回值就是该表达式的结果。用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数。
# -*- coding=utf-8 -*-
def add(a, b):
return a + b
n, m = map(int, raw_input().split())
print add(n, m)
# --------匿名函数写法----------
res = lambda n, m: n + m
print res(n, m)
----------------
# 求1-19内的奇数
res = lambda n: n % 2 == 1
L = list(filter(res, range(1, 20)))
print L
三、python运用
3.1 根据条件筛选数据
案例1.过滤掉列表中的负数
# -*- coding=utf-8 -*-
from random import randint
data = [randint(-10, 10) for _ in xrange(10)]
print data # [7, 1, 5, 7, 1, 1, -3, -8, -4, -10]
# 过滤小于0的数
print filter(lambda x: x >= 0, data) # [7, 1, 5, 7, 1, 1]
print [x for x in data if x >= 0] # [7, 1, 5, 7, 1, 1]
案例2.挑出value大于90的元素
# -*- coding=utf-8 -*-
from random import randint
dic = {x: randint(60, 100) for x in range(1, 21)}
# 挑出value大于90的元素
print {k: v for k, v in dic.iteritems() if v > 90}
案例3.# 选出可以被3整除的数
# -*- coding=utf-8 -*-
from random import randint
data = set(randint(-10, 10) for _ in xrange(10))
# 选出可以被3整除的数
print set(x for x in data if x % 3 == 0)
案例4.如何统计序列中元素的出现频度
# -*- coding=utf-8 -*-
from random import randint
data = [randint(0, 20) for _ in xrange(30)]
print data
# 如何统计序列中元素的出现频度
# data中的每一个元素作为key,0作为value
dic = dict.fromkeys(data, 0)
print dic
for x in data:
dic[x] += 1
print dic
-------------
# -*- coding=utf-8 -*-
from random import randint
from collections import Counter
data = [randint(0, 20) for _ in xrange(30)]
print data
dic = Counter(data)
print dic
#统计出现最多的三个元素
dic = Counter(data)
print dic.most_common(3)
3.2 如何让字典保持有序
案例:根据答题时间依次打印选手的成绩
# -*- coding=utf-8 -*-
from collections import OrderedDict
d = OrderedDict()
d['milly'] = (1, 23)
d['luc'] = (2, 33)
d['poe'] = (3, 27)
d['mana'] = (4, 26)
print d
四、目前遇到的py2与py3的区别
-
print 语句没有了,取而代之的是 print() 函数。 Python 2.6 与 Python 2.7 部分地支持这种形式的 print 语法。在 Python 2.6 与Python 2.7 里面,以下三种形式是等价的:
print "fish" print ("fish") # 注意print后面有个空格 print("fish") # print()不能带有任何其它参数
如果 Python2.x 版本想使用使用 Python3.x 的 print 函数,可以导入 future 包,该包禁用 Python2.x 的 print 语句,采用 Python3.x 的 print 函数
from __future__ import print_function data = [_ for _ in xrange(10)] for i in data: print(i, end=' ')
-
Unicode
Python3.x 源码文件默认使用 utf-8 编码,所以使用中文就更加方便
python2要在前面加
#-*- coding=utf-8 -*-
-
除法运算
首先来说 / 除法:
在 Python 2.x 中 / 除法就跟我们熟悉的大多数语言,比如 Java 和 C ,整数相除的结果是一个整数,把小数部分完全忽略掉,浮点数除法会保留小数点的部分得到一个浮点数的结果。
在 Python 3.x 中 / 除法不再这么做了,对于整数之间的相除,结果也会是浮点数。
而对于 // 除法,这种除法叫做 floor 除法,会对除法的结果自动进行一个 floor 操作,在 Python 2.x 和 Python 3.x 中是一致的。
-
xrange
在 Python 2 中 xrange() 创建迭代对象的用法是非常流行的。比如: for 循环或者是列表/集合/字典推导式。
这个表现十分像生成器(比如。“惰性求值”)。但是这个 xrange-iterable 是无穷的,意味着你可以无限遍历。
由于它的惰性求值,如果你不得仅仅不遍历它一次,xrange() 函数 比 range() 更快(比如 for 循环)。尽管如此,对比迭代一次,不建议你重复迭代多次,因为生成器每次都从头开始。
在 Python 3 中,range() 是像 xrange() 那样实现以至于一个专门的 xrange() 函数都不再存在(在 Python 3 中 xrange() 会抛出命名异常)。
-
不等运算符
Python 2.x中不等于有两种写法 != 和 <>
Python 3.x中去掉了<>, 只有!=一种写法,还好,我从来没有使用<>的习惯
五、今日总结
在廖雪峰的python教程和菜鸟教程看了很多关于高阶函数的知识,包括复现上面的例子,自己也写了很多小案例,慢慢的好像懂了那么些,很多例子也知道怎么来的了。不懂得多看文档和视频教程,多上手实践,这样能更快掌握新学的知识。