Python 学习笔记二
2017-04-21 13:59
162 查看
高级特性
切片
如果想取数组中的部分元素,则可以通过在数组中使用[start:end]实现,类似于JavaScript中的
slice(start, end);其中
start和end都可以为负数,表示以倒数的方式来计算,也可以只写一个负数,也可以什么都不写只有一个:,表示复制整个数组。
如果是
::,表明每隔一段来取一个,比如:
>>> 'ABCDEFG'[::2] 'ACEG'
也可以这么写,前6个数每2个取1个:
>>> 'ABCDEFG'[:6:2] 'BDF'
切片适用于类似数组的类型,比如 字符串,list,tuple等等。
迭代
在python中,迭代使用的是for...in...关键字,同时只要是
可迭代对象,都可以迭代,比如json对象等等。
那么,如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断:
>>> from collections import Iterable >>> isinstance('abc', Iterable) # str是否可迭代 True >>> isinstance([1,2,3], Iterable) # list是否可迭代 True >>> isinstance(123, Iterable) # 整数是否可迭代 False
列表生成式
将所有的表达式放到[]里面去执行:
>>> [x * x for x in range(1, 11) if x % 2 == 0] [4, 16, 36, 64, 100]
生成器
怎么创建一个生成器呢?将
列表生成式中外围的
[]改为
()即可
可以通过
next函数获取
generator的下一个返回值。
>>> 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) 0 >>> next(g) 1
在函数中使用
yield关键字,其作用类似于return+print
def odd(): print('step 1') yield 1 print('step 2') yield(3) print('step 3') yield(5)
在执行过next后,再次执行的时候则从上一次执行
yield后的位置继续执行,遇见
yield则返回,但是如果执行到后面已经没有
yield后,则会报错。
>>> o = odd() >>> next(o) step 1 1 >>> next(o) step 2 3 >>> next(o) step 3 5
如果不想用
next,一步一步的计算,同样的可以使用循环。
def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b n = n + 1 return 'done' >>> for n in fib(6): ... print(n) ... 1 1 2 3 5 8
如果想要捕捉到返回值,则在找不到next的时候(异常)返回,例如:
>>> g = fib(6) >>> while True: ... try: ... x = next(g) ... print('g:', x) ... except StopIteration as e: ... print('Generator return value:', e.value) ... break ... g: 1 g: 1 g: 2 g: 3 g: 5 g: 8 Generator return value: done
迭代器
注意区分Iterable和Iterator,前者是可迭代的,后者是迭代器(类似于C++中vector和::iterator),同样的,可以使用
isinstance来判断;
函数式编程
高阶函数
map/reduce
map(函数,Iterable),将可迭代对象中的元素执行函数以后生成一个新的iterator;
>>> def f(x): ... return x * x ... >>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> list(r) [1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce函数必须接收两个参数,一个是函数,一个是list,其重点在于将list中的元素进行函数计算后作用到下一个元素上。
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
比如这么用:
from functools import reduce def str2int(s): def fn(x, y): return x * 10 + y def char2num(s): return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s] return reduce(fn, map(char2num, s))
filter
用于过滤序列,返回一个新的序列;和
map一样,同样接收一个函数和序列,但不同的是,
filter使用函数对序列中的元素进行筛选,也就是说该函数是一个
bool函数,将值传递进去后只有返回成功才将该值加入到新的队列中。
def is_odd(n): return n % 2 == 1 list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])) # 结果: [1, 5, 9, 15]
如果这不是一个筛选函数呢?python则认为均为false,也就是不加入任何元素,返回空序列。
sorted
对序列进行排序,后面还可以加上key来指定排序函数,还可以加上reverse表示反向排序;class Student: def __init__(self, name, grade, age): self.name = name self.grade = grade self.age = age def __repr__(self): return repr((self.name, self.grade, self.age)) # student_objects = [ # Student('john', 'A', 15), # Student('jane', 'B', 12), # Student('dave', 'B', 10), #] # 使用lambda sorted(student_objects, key=lambda student: student.age, reverse=True) # sort by age # [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)] # 或者使用attrgetter sorted(student_objects, key=attrgetter('age'), reverse=True)
闭包
当你调用了一个函数A,这个函数A返回内部的函数B,这个返回的函数B就是闭包;def func(name): def inner_func(age): print 'name:', name, 'age:', age return inner_func bb = func('the5fire') bb(26) # >>> name: the5fire age: 26
匿名函数
lambda表示匿名函数(和C++ 11.0中的lambda表达式类似),格式为:lambda x : x * x
冒号前面表示参数,返回值为冒号后面的计算结果。
装饰器
需要单独写一篇文章进行总结(重要)总之就是在不改变一个函数的前提下(其它调用该函数的也不需要改变,只需要在调用函数前面加上
@decorator就行),往该函数上加功能进行任意的扩展。
偏函数
functools.partial表示的是将函数“保存”下来,返回来一个在原来函数的基础上重新定义的函数;
例子:
import functools def add(a, b): return a + b add(4, 2) 6 plus3 = functools.partial(add, 3) plus5 = functools.partial(add, 5) plus3(4) 7 plus5(10) 15
除此之外,
functools模块还包括:
functool.update_wrapper:从原始对象拷贝或加入现有partial对象
functool.wraps:调用函数装饰器partial
functools.reduce:等同于内置函数reduce()
functools.cmp_to_key:将老式鼻尖函数转换成key函数,用在接受key函数的方法中
functools.total_ordering:它是针对某个类如果定义了__lt__、le、gt、__ge__这些方法中的至少一个,使用该装饰器,则会自动的把其他几个比较函数也实现在该类中。
面向对象编程
继承和多态
对于静态语言(例如Java)来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则,将无法调用run()方法。对于Python这样的动态语言来说,则不一定需要传入Animal类型。我们只需要保证传入的对象有一个run()方法就可以了:
实例属性和类属性
在编写程序的时候,千万不要把实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性,个人不建议在示例上添加任何新的属性,在类中加上属性即可。
相关文章推荐
- Python学习笔记:Python Language Features
- Boost.Python学习笔记
- Python 学习笔记 - 4.if 表达式
- python文件读写实例学习笔记
- Python 学习笔记(1)
- python(异常处理机制,学习笔记摘要)
- python学习笔记(1)
- python学习笔记,整形,字符串
- Python学习笔记1
- Python学习笔记
- if __name__ (python学习笔记一,注意前面是双下划线)
- python学习笔记(二)
- python学习笔记(2)
- python学习笔记1
- Python学习笔记(一)
- [原创]Ruby学习笔记(4)-闰年、季节和月份天数的Ruby版和Python版
- Python学习笔记 Module
- Python 正则式学习笔记
- Python 学习笔记 - 2.自省