流畅的python 函数
列表推导:
通常只用列表推到来创建新的列表,且尽量简短,它的作用只有一个,就是生成列表,生成其他序列就要用到生成器表达式了。
a = range(10)
b = [x*x for x in a] # 列表推导式
print(b)
生成器表达式:
虽然列表推导可以创建元组,数组,或其他序列类型,但生成器表达式是更好的选择。生成器表达式背后遵循了迭代器协议,可以逐个的产出元素,而不是先建立一个完整的列表。写法与列表推导式非常的相似:
# 生成器表达式
a = range(10)
b = (x*x for x in a) # 生成器表达式
print(tuple(b))
列表推导与生成器表达式对比:
colors = ['white', 'black', 'red']
sizes = ['S', 'M', 'L']
# 列表推导
for x in [(color, size) for color in colors for size in sizes]:
print(x)
# 生成器表达式
for x in ((color, size) for color in colors for size in sizes):
print(x)
用了声称其表达式后,内存里不会留下一个有9个组合的列表,因为生成器表达式只有每次执行for循环时才会产生一个元素。
但是列表推导首先会新建一个列表。
将函数视作对象:
# 定义函数
def factorial(n):
"""
定义函数计算n的阶乘
:param n:
:return:
"""
return 1 if n<2 else n*factorial(n-1)
# 将函数视作对象
fact = factorial
print(fact(10))
# 函数作为参数传递
a = range(10)
b = map(factorial, a)
print(list(b))
高阶函数:接收函数为参数或者将函数作为结果返回的函数叫做高阶函数,例如map()函数
tp = ["apple", 'peaches', 'holland', 'newspaper_stand']
tpp = sorted(tp, key=lambda x: len(x))
print(tpp)
def reverse(word):
"""
逆序输出
:param word:
:return:
"""
return word[::-1]
tpp = map(reverse, tp)
print(list(tpp))
常用的高价函数:map(), filter(), reduce(),函数式语言通常会提供这三个高阶函数
for x in map(factorial, range(10)):
print(x)
for x in filter(lambda x: x % 2 == 0, range(20)):
print(x)
python3中map(),filter()函数返回的是生成器!
from functools import reduce
from operator import add # add(x,y)函数
print(reduce(add, range(100)))
sum(), reduce()函数的通用思想是把某个操作连续运用到序列的元素上,累计之前的结果,把一系列值规约为一个值
all(iter), any(iter)函数
匿名函数:
lambda表达式。一般作为参数传递给高阶函数
可调用对象:
判断对象是否可调用print(callable(factorial))
python数据模型指出七种可调用的类型:
1.用户自定义函数 def
2.内置函数
3. 内置方法
4. 方法 类中定义的函数
5. 类
6. 类的实例
7. 生成器函数
从定位参数到仅限关键字参数:
python提供了极为灵活的参数处理机制:调用*和**展开可迭代对象,映射到单个参数
def tag(name, *content, cls=None, **attrs):
if cls is not None:
attrs['class'] = cls
if attrs:
attr_string = " ".join(' %s="%s"' % (key, value) for key, value in attrs.items())
else:
attr_string = ''
if content:
return '\n'.join('<%s%s>%s<%s>' % (name, attr_string, c, name) for c in content)
else:
return '<%s%s />' % (name, attr_string)
对函数的调用:
print(tag("br")) # 传入单个定位参数
print("-"*30)
print(tag('p', 'hello')) # 第一个后面的人一个参数会被content捕获,存入元组
print('-'*30)
print(tag('p', 'hello', 'world')) # 第一个后面的人一个参数会被content捕获,存入元组
print('-'*30)
print(tag('p', 'hello', 'world', cls='sidebar')) # cls只能作为关键字参数传入
print('-'*30)
print(tag('p', 'hello', 'world', id=23, href='http://sina.com', cls='sidebar'))
调用的结果:(函数的参数收集)
operator模块:
operator模块为多个算术运算符提供了对应的函数,从而避免在一些地方写匿名函数:
例如计算阶乘:
from functools import reduce
def fact1(n):
return reduce(lambda x, y: x*y, range(1, n+1))
print(fact1(10))
为了避免写lambda这样的匿名函数:
from functools import reduce
from operator import mul
def fact1(n):
return reduce(mul, range(1, n+1))
print(fact1(10))
operator模块中itemgetter和attrgetter函数:能替代从元素中取出元素或者读取对象属性的lambda表达式:
lambda x: x[n] 或者lambda x: x["attr"]
例如:
person_data = [('Ann', 34, 'boy', 'student'),
('Tom', 23, 'boy', 'doctor'),
('Liky', 21, 'girl', 'sailor'),
('Kate', 19, 'girl', 'queen')]
for x in sorted(person_data, key=lambda x: x[1]):
print(x)
可以写为:
from operator import itemgetter
person_data = [('Ann', 34, 'boy', 'student'),
('Tom', 23, 'boy', 'doctor'),
('Liky', 21, 'girl', 'sailor'),
('Kate', 19, 'girl', 'queen')]
for x in sorted(person_data, key=itemgetter(1)):
print(x)
输出结果:
将多个值传递给itemgetter,它构建的函数会返回提取的值构成的元组:
from operator import itemgetter
cc_person = itemgetter(0, 2, 3)
person_data = [('Ann', 34, 'boy', 'student'),
('Tom', 23, 'boy', 'doctor'),
('Liky', 21, 'girl', 'sailor'),
('Kate', 19, 'girl', 'queen')]
for x in person_data:
print(cc_person(x))
返回值:
attrgetter和itemgetter函数类似,它创建的函数根据名称提取对象的属性,同样也可以将多个属性传递给它:
这里会用到具名元组namedtuple:
from operator import itemgetter
from operator import attrgetter
from collections import namedtuple
person_data = [('Ann', 34, 'boy', 'student', (23.4, 90.5)),
('Tom', 23, 'boy', 'doctor', (12.3, 56.1)),
('Liky', 21, 'girl', 'sailor', (21.8, 98.1)),
('Kate', 19, 'girl', 'queen', (32.1, 89))]
LatLong = namedtuple('LatLong', ['lat', 'long']) # fieldname参数可以是列表
people = namedtuple('people', 'name age sex occupation coord') # feildname参数也可以是这样
people_list = [people(name, age, sex, occupation, LatLong(lat, long)) for
(name, age, sex, occupation, (lat, long)) in person_data]
# 具名元组的访问
print(people_list[0])
print('-'*30)
print(people_list[1].occupation) # 通过 . 运算符访问具名元组的元素
print('-'*30)
print(people_list[2].coord.long)
print('-'*30)
for x in sorted(people_list, key=attrgetter('age')):
print(x)
print('-'*30)
name_lat = attrgetter('name', 'coord.lat')
for x in sorted(people_list, key=attrgetter('age')):
print(name_lat(x))
注意具名元组的使用!
运行结果:
methodcaller()函数,会在对象上调用参数值指定的方法:
from operator import methodcaller
s = 'hello world'
uppercase = methodcaller('upper')
print(uppercase(s))
replacement = methodcaller('replace', ' ', '-')
print(replacement(s))
functools.partial冻结参数:
# 冻结tag()函数的部分参数
from functools import partial
picture = partial(tag, 'img', cls='pic-frame') # 冻结tag()函数的定位参数以及cls参数
print(picture('pict1', 'pict2'))
print('-'*30)
print(picture('pict1', 'pict2', src='www.xxx.com'))
partial函数对于函数的部分参数进行了冻结,再调用的我们只需要关心我们需要改变的参数即可
--------------------------------------------------------------------------------------------------