Python的高级特性有哪些?

本文和大家分享的主要是python开发中的一些新特性,一起来看看吧,希望对大家有所帮助。

列表生成式(List Comprehensions)

切片和迭代就不说了,这里直接先看一下列表生成式吧,从名字就能大概猜出这是生成列表的一些方法,比如:如何生成 [1*1, 2*2, ... ,10*10] ?可以用循环不断向列表尾部添加元素,如果使用 pythonic 的方法,也就是列表生成式,则是:

>>> [x * x for x in range(1, 11)]

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

后面还能跟上 if 判断,例如:

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

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

这样,本来需要使用循环写4,5行的代码,使用一行就解决了,直观明了。

还能使用两个 for 循环生成全排列:

>>> [m + n for m in ’ABC’ for n in ’XYZ’]

[’AX’, ’AY’, ’AZ’, ’BX’, ’BY’, ’BZ’, ’CX’, ’CY’, ’CZ’]

这样如何添加 if 判断呢?可以在每个 for 语句后添加,或者在最后添加:

>>> [m + n for m in ’ABC’ if m < ’C’ for n in ’XYZ’ if n < ’Z’]

[’AX’, ’AY’, ’BX’, ’BY’]>>> [m + n for m in ’ABC’ for n in ’XYZ’ if n < ’Z’ and m < ’C’]

[’AX’, ’AY’, ’BX’, ’BY’]

也可以同时在一个 for 语句中迭代多个变量,比如dict的items()可以同时迭代key和value:

>>> d = {’x’: ’A’, ’y’: ’B’, ’z’: ’C’ }>>> [k + ’=’ + v for k, v in d.items()]

[’y=B’, ’x=A’, ’z=C’]

差不多就是这样了~

但是以前总是写 C++ ,这种思维模式很难改过来,只能慢慢在使用中熟悉这种语法,习惯了就能够在下意识中写出来了。

生成器(Generator)

为什么要使用生成器?廖大的教程中说得很详细,这里再简述一下:

1.因为列表的内容放在内存中,而受到内存限制,列表的容量有限。

2.如果我们只访问极少的元素,那么存在极大的空间浪费。

3.而生成器可以一边迭代一边计算下一个值,理论上,该过程可以无限进行下去,并且不会占用大量内存。

这里只是简单介绍一下,更详细的请 Google 哈~

如何创建生成器?第一种方法类似于前面讲到的列表生成式,只需要将[]改为()即可:

>>> 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 objectat 0x1022ef630>

可以看到,方法上大致相同,[]得到的是一个已经得到所有值的列表,()得到的是一个生成器,它们都能使用 for 循环来迭代,但是生成器不能使用下标访问,并且只能被迭代一次,再次迭代则会有 StopIteration 的异常:

>>> for i in g:... print(i)

...0149162536496481>>> for i in g:... print(i)

...>>> next(g)

Traceback (most recent call last):

File "", line 1, in

StopIteration

不过当我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。

如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现,比如,著名的斐波那契数列:

def fib(max):

n, a, b = 0, 0, 1

while n < max:

yield b

a, b = b, a + b

n = n + 1

return ’done’

关于 yield 这个关键字,我在刚学 python 的时候也纠结了很久,直到看到生成器的时候才大致明白,大家搜索一下就能大致明白了,我觉得这东西说起来麻烦,只说一两句又怕说错。廖大的教程中是这样说的:

函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

可能有点难理解,不过明白了就很好说了。

当然,函数中还可以添加 return,在一个 generator function 中,如果没有 return,则默认执行至函数完毕,如果在执行过程中 return,则直接抛出 StopIteration 终止迭代。

例如上面的例子,我们在迭代时发现并没有出现 ’done’ 这串字符,是因为 return 的值被当作 Exception Value 了,如果要显示出来,则可以这样:

>>> 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

迭代器(Iterator)

可直接作用于 for 循环的对象被称为可迭代对象,可以用 isinstance() 函数判断是否为可迭代对象:

>>> from collections import Iterable>>> isinstance([], Iterable)True>>> isinstance({}, Iterable)True>>> isinstance(’abc’, Iterable)True>>> isinstance((x for x in range(10)), Iterable)True>>> isinstance(100, Iterable)False

而可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。当然,仍然可以使用isinstance()判断一个对象是否是Iterator对象:

>>> from collections import Iterator>>> isinstance((x for x in range(10)), Iterator)True>>> isinstance([], Iterator)False>>> isinstance({}, Iterator)False>>> isinstance(’abc’, Iterator)False

通过上面两个例子,可以这样理解:生成器和 list,tuple,str 等都是 Iterable 对象,生成器同时还是 Iterator 对象,而 list 等不是。那么能否直接将 Iterable 对象转换成 Iterator 对象呢?

可以使用iter()函数:

>>> isinstance(iter([]), Iterator)

True

>>> isinstance(iter(’abc’), Iterator)

True

其实,Iterator 对象表示的是一个数据流,我们可以把这个数据流看做是一个有序序列,但却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以 Iterator 的计算是惰性的,只有在需要返回下一个数据时它才会计算。Iterator甚至可以表示一个无限大的数据流,但 list,tuple 什么的是不可能这样的。

总结

过了个寒假没碰代码,相当于复习了一遍啊,其实这里说到的特性是很浅显的,理解起来不难,等全部差不多复习完还得再深入一点,理解更多才行。

来源:SegmentFault

时间: 2024-10-12 22:54:56

Python的高级特性有哪些?的相关文章

python之高级特性

掌握了Python的数据类型.语句和函数,基本上就可以编写出很多有用的程序了. 比如构造一个1, 3, 5, 7, ..., 99的列表,可以通过循环实现: L = [] n = 1 while n <= 99: L.append(n) n = n + 2 取list的前一半的元素,也可以通过循环实现. 但是在Python中,代码不是越多越好,而是越少越好.代码不是越复杂越好,而是越简单越好. 基于这一思想,我们来介绍Python中非常有用的高级特性,1行代码能实现的功能,决不写5行代码.请始终

python函数高级特性

掌握了Python的数据类型.语句.函数,基本可以编写出很多有用的程序了.但是Python中,代码不是越多越好,而是越少越好.代码不是越复杂越好,而是越简单越好.基于这一思想,我们来介绍python中非常有用的高级特性,1行代码能实现的功能绝不用5行代码,请始终牢记,代码越少,开发效率越高. 切片(Slice) 取一个list或tuple的部分元素是非常常见的操作,比如,一个list如下: L=['Micheal','Sarah','Bob','Jack'] 当我们要取前N个元素,使用循环操作很

Python的高级特性10:无聊的@property

@property装饰器其实有点无聊,单独拿出来作为一个知识点其实没必要,尽管它可以将方法变成属性,让get和set方法更好用,但是,它破坏了python的简洁(不是代码的简洁而是指语法上). 下面来说明为什么我会这么说. 首先,看一个使用property. class Student(object): @property def testname(self): return self.name @testname.setter def testname(self,name): self.nam

Python的高级特性11:拓展基本数据类型(dict)

字典的创建有两种方式,如果出现In [26]这样的赋值方式就会报错. In [17]: s['name'] = 'alex' In [18]: s['sex'] = 'male' In [19]: s Out[19]: {'name': 'alex', 'sex': 'male'} In [20]: s = {'name':'alex','sex':'male'} In [21]: s Out[21]: {'name': 'alex', 'sex': 'male'} In [22]: t = {

python的高级特性3:神奇的__call__

__call__是一个很神奇的特性,只要某个类型中有__call__方法,,我们可以把这个类型的对象当作函数来使用. 也许说的比较抽象,举个例子就会明白. In [107]: f = abs In [108]: f(-10) Out[108]: 10 In [109]: dir(f) Out[109]: ['__call__', '__class__', '__delattr__', '__dir__', ...] 上例中的f对象指向了abs类型,由于f对象中有__call__方法,因此f(-1

Python的高级特性1:容易忽略的不可变类型

python中有一些容易忽略的不可变类型(str,integer,tuple,None) #错误演示 In [45]: def demo(lst=[]): ....: lst.append("hello") ....: return lst ....: In [46]: demo() Out[46]: ['hello'] In [47]: demo() Out[47]: ['hello', 'hello'] 廖雪峰的python教程有提到这一块,但并没有太细致.在这里,由于lst是一个

Python的高级特性2:列表推导式和生成器

一.列表推导式 1.列表推导式是颇具python风格的一种写法.这种写法除了高效,也更简短. In [23]: ['i:el' for i,el in enumerate(["one","two","three"])] Out[23]: ['i:el', 'i:el', 'i:el'] enumerate是内建函数,可以让列表获得“下标”的属性.而如果不用列表推导式,上例需要这么写 In [24]: lst = ["one",

Python的高级特性之切片、迭代、列表生成式、生成器

切片 切片就是获取一个list.tuple.字符串等的部分元素 1 l = range(100) 2 #取[0,5)元素 3 print(l[:5]) #[0, 1, 2, 3, 4] 4 #在[0,99]中每隔10个元素取一个 5 print( l[::10]) #[0, 10, 20, 30, 40, 50, 60, 70, 80, 90] 6 #取最后五个元素 7 print( l[-5 : ]) #[95, 96, 97, 98, 99] 8 9 str = "www.genekang.

Python的高级特性7:使用__slots__真的能省很多内存

在伯乐在线上看到了这篇文章,用Python的 __slots__ 节省9G内存,于是想测试下,对单个类,用__slots__节省内存效果会不会明显. 看完这个例子后,我们也会明白__slots__是用来干嘛的. :import sys :class test(object): : def __init__(self,name): : self.name = name : : :class test2(object): : __slots__ = ["name"] : def __ini