《对廖雪峰老师的Python教程的学习小结二》

将以下内容作为第二部分。内容中涉及的程序均来源于廖老师的Python教程(网址为https://www.liaoxuefeng.com/wiki/1016959663602400/)。

四、高级特性

引入高级特性,可以缩减代码量。

1. 切片

L[0:3]取列表中的前3个元素,等价于L[:3]。

L[-2:]获取最后的2个元素。L[-2:-1]获取倒数第2个元素。

L[:10:2]从第1个元素开始每隔2个开始获取元素,直到第10个元素。

L[::5]以5为步长来获取列表中所有元素。

L[:]获取列表中的所有元素。

对于tuple和str,也可以用上面的切片方式获得元素。

去掉字符串首尾的空字符:

def trim(s):

  while s[:1]==’’

s=s[1:]

  while  s[-1:]==’’

s=s[:-1]

  return s

2. 迭代

for ... in...

字典的例子:

>>> d = {'a': 1, 'b': 2, 'c': 3}

>>> for key in d:

...     print(key)

获得的是key值。迭代出的结果并不一定是按照a b c的顺序输出的。如果迭代value的话,应该是用for value in d.values()迭代key和value的话,应该是用for k, v in d.items()

判断对象是否是可迭代对象的方式:Iterable。

>>> from collections import Iterable

>>> isinstance('abc', Iterable) # str是否可迭代

True

>>> isinstance([1,2,3], Iterable) # list是否可迭代

True

>>> isinstance(123, Iterable) # 整数是否可迭代

False

若想变为索引-元素的形式,应该用enumerate,如:

>>> for i, value in enumerate(['A', 'B', 'C']):

...     print(i, value)

0 A

1 B

2 C

3. 列表生成式

>>> [x * x for x in range(1, 11) if x % 2 == 0]

[4, 16, 36, 64, 100]

isinstance(xxx, str) 用isinstance判断变量xxx是否是字符串str类型。如果是的话,则结果为True;否则结果是False。

4. 生成器

从节省存储空间的角度出发,引入生成器。如下所示,即将[ ]换为( )即可。

>>> L = [x * x for x in range(10)]

>>> L

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

>>> g = (x * x for x in range(10))     #即获得生成器

>>> g

<generator object <genexpr> at 0x1022ef630>

依次用next(g)可以依次获取g中的元素。为了更好地获取g中的元素,采用for循环的方式来代替next,有

>>> g = (x * x for x in range(10))

>>> for n in g:

...     print(n)

0

1

4

9

16

25

36

49

64

81

定义generator,有

def fib(max):

    n, a, b = 0, 0, 1

    while n < max:

        yield b          #把print(b)替换为yield b,变为generator

        a, b = b, a + b

        n = n + 1

    return 'done'

因而,可以得到

>>> f = fib(6)

>>> f

<generator object fib at 0x104feaaa0>

遇到yield返回。再执行时,从开始yield后执行。while n < max是设置的终止循环的条件。除此之外,可以采用for或者while来实现next()的作用。

>>> for n in fib(6):

...     print(n)

1

1

2

3

5

8

5. 迭代器

和之前的一样,可以用isinstance(xxx, Iterable)来判断对象xxx是否是Iterable对象,即可迭代对象

可以用next()函数调用并不断返回下一个值的对象称为迭代器Iterator

>>> isinstance([], Iterator)

False

可以用isinstance判断对象是否是迭代器。

注:生成器都是迭代器。可以用iter()将可迭代对象变为迭代器。不是迭代器的可迭代对象有list, str, dict等。原因在于迭代器会不断地返回下一个元素,没有指定数据的数量大小。

总结:

  1. 可以用于for循环的对象都是Iterable。
  2. 可以用作next()的对象都是Iterator。
  3. list,dict,str是Iterable而不是Iterator,可以通过iter()转变为Iterator。
  4. Python的for循环本质上是通过next()来实现的(iter()将Iterable转变为Iterator,再循环使用next())。

五、函数式编程

函数式编程:抽象程度高。

            允许将函数作为参数传入另一个函数,也支持返回一个函数。

纯函数式编程:函数中没有变量。只要给定输入,就可以确定输出,这样的函数式是没有副作用的。Python是允许在函数中使用变量的,因而不是纯函数式编程。

1. 高阶函数

>>> f = abs

>>> f(-10)    #和abs(-10)是等效的

10

变量f指向函数abs,也可以通过变量来调用函数。

可以认为函数名abs也是一个变量,它指向一个可以实现绝对值计算的函数。当把该变量指向其它对象时,会出现错误,如下所示:

>>> abs = 10

>>> abs(-10)

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

TypeError: 'int' object is not callable

函数可以作为参数传入另一个函数中,支持将函数作为参数来传入的函数被称为高阶函数。

(1)map/reduce

map:输入两个参数(函数和Iterable),输出Iterator。

reduce:将内部的函数的结果和序列中的下一个元素做相关操作。

例子1:lambda函数实现将str转化为int

from functools import reduce

DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}

def char2num(s):

    return DIGITS[s]

def str2int(s):

    return reduce(lambda x, y: x * 10 + y, map(char2num, s))

例子2:将str转化为浮点数

digits = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}

def str2float(s):

    def fn(x, y):

        return x * 10 + y

    def char2num(s):

        return digits[s]

    # 用index查找小数点在数字的第几位,然后用整个长度减去这个长度就可以得到有多少个小数位

    # 注意要多减1,因为小数点自身的位置也要减掉。

    dot = len(s) - s.index('.') -1

    # 去掉小数点

   a = s.replace('.', '')

    # 按照整数的方法来运算,最好再乘一个分位数,这样就转为float了。

    return reduce(fn, map(char2num, a)) * 0.1**dot

(2) filter

filter把传入的函数作用于序列中的每个元素,根据返回值是True还是False,确定是保留还是舍弃该元素。例如下面的代码(实现将list中的空字符串去掉):

def not_empty(s):

    return s and s.strip()

list(filter(not_empty, ['A', '', 'B', None, 'C', '  ']))# 结果: ['A', 'B', 'C']

由于filter()返回的是一个Iterator,和map一样,需要用list()函数获取结果并返回list。

例子:用filter筛选1-1000的回数

def is_palindrome(n):

    return str(n) == str(n)[::-1]

output = filter(is_palindrome,range[1,1001])

print('1-1000:',list(output))

(3)sorted

用于排序。使用sorted,默认是按照从小到大的顺序排列的。

>>> sorted([36, 5, -12, 9, -21], key=abs)

[5, 9, -12, -21, 36]

接受key实现自定义排序。

>>> sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)

['Zoo', 'Credit', 'bob', 'about']

reverse=True保证是按照正序排列的。

分别按照姓名、成绩进行排序,有

L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]

def by_name(t):

    return t[0]   #返回tuple内部第一个元素,也就是name

L1 = sorted(L,key = by_name)

print(L1)

def by_score(t):

    return -t[1]  #返回tuple内部第二个元素的负值,也就是score的负值

L2 = sorted(L,key = by_score)

print(L2)

2. 返回函数

闭包:

def lazy_sum(*args):

    def sum():

        ax = 0

        for n in args:

            ax = ax + n

        return ax

    return sum

>>> f = lazy_sum(1, 3, 5, 7, 9)

>>> f                             #返回的是函数,而不是结果。

<function lazy_sum.<locals>.sum at 0x101c6ed90>

>>> f() #此时函数才执行,得到结果。

25

我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种程序结构被称为“闭包”

注:返回函数不要引用任何循环变量,或者后续会发生变化的变量。详见该部分的具体实例讲解!(自己还未弄明白)

3. 装饰器

可以动态地增加函数的功能,而且不改变原有的函数的定义。

这部分自己还未弄懂具体内容。

4. 偏函数

functools.partial来实现。

>>> import functools

>>> int2 = functools.partial(int, base=2)

>>> int2('1000000')

64

>>> int2('1010101')

85

实际上,偏函数就是把函数的某些参数固定住(设置为默认参数),返回一个新的函数。常用于函数的参数比较多的情况,调用起来更加方便。

六、模块

一个.py文件就是一个模块。

可以用包来组织模块,避免模块名出现冲突。对于每一个包,都有一个_init_.py文件,用来说明是一个包。文件_init_py是一个模块,模块名是上层目录的名字

注:模块名的命名遵循Python中的变量命名规则。

命名模块时不要和系统的模块相冲突,通过import 模块名来进行验证,如果没有错误的话则说明是有该模块的。

1. 使用模块

if __name__=='__main__':

    test()

上述是模块hello中的一段代码。在其它地方导入hello模块时,上述的if判断将失效。

对于__xxx__这样的变量,是特殊变量。

若只想让函数和变量在模块内部使用,可以用_前缀来命名它们。例如__name__、__author__。对于_xxx或__xxx这样的变量是private的。正常情况下定义的函数或者变量是遵从变量命名规则的。

2. 安装第三方模块

pip install 名称

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值