您的位置:首页 > 编程语言 > Python开发

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()方法就可以了:

实例属性和类属性


在编写程序的时候,千万不要把实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性,个人不建议在示例上添加任何新的属性,在类中加上属性即可。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: