流畅的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函数对于函数的部分参数进行了冻结,再调用的我们只需要关心我们需要改变的参数即可

--------------------------------------------------------------------------------------------------

posted @ 2019-01-16 15:12  Alpha205  阅读(99)  评论(0编辑  收藏  举报