一、生成器
生成器表达式背后遵守了迭代器协议,可以逐个地产出元素,而不是先建立一个完整的列表,然后再把这个列表传递到某个构造函数里。能够节省内存使用。
colors = ['black', 'white']
sizes = ['s', 'm', 'l']
for tshirt in ('%s %s' % (c, s) for c in colors for s in sizes):
print tshirt
使用生成器函数yield的等差数列
def aritprog_gen(begin, step, end=None):
result = type(begin + step)(begin)
forever = end is None
index = 0
while forever or result < end:
yield result
index += 1
result = begin + step * index
二、枚举:Enumerate
enumerate在字典上是枚举、列举的意思。对于一个可迭代/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列
利用它可以同时获得索引和值,多用于在for循环中得到计数
list1 = ["这", "是", "一个", "测试"]
for index, item in enumerate(list1):
print index, item
enumerate还可以接收第二个参数,用于指定索引起始值
for index, item in enumerate(list1, 2):
print index, item
如果要统计文件的行数,可以这样写:
with open('my.txt', 'r') as m:
count = len(m.readlines())
这种方法简单,但是可能比较慢,当文件比较大时甚至不能工作;可以利用enumerate()
count = 0
with open('my.txt', 'r') as m:
for index, line in enumerate(m):
count += 1
三、具名元组:Namedtuple
用以构建只有少数属性但是没有方法的类,比如数据库条目。用namedtuple构建的类的实例所消耗的内存跟元组是一样的,因为字段名都被存在对应的类里面。
创建一个具名元组需要两个参数,一个是类名,另一个是类的各个字段的名字。后者可以是由数个字符串组成的可迭代对象,或者是由空格分隔开的字段名组成的字符串
from collections import namedtuple
Card = namedtuple('Card', ['rank', 'suit'])
City = namedtuple('City', 'name country population coordinates')
tokyo = City('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
print tokyo # City(name='Tokyo', country='JP', population=36.933, coordinates=(35.689722, 139.691667))
print tokyo.coordinates # (35.689722, 139.691667)
四、迭代器
① getitem
class FrenchDeck:
ranks = [str(n) for n in range(2, 11)] + list('JQKA')
suits = 'spades diamonds clubs hearts'.split()
def __init__(self):
self._cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks]
def __len__(self):
return len(self._cards)
def __getitem__(self, position):
return self._cards[position]
因为 getitem 方法把 [] 操作交给了 self._cards 列表,所以我们的 deck 类自动支持切片(slicing)操作。
deck = FrenchDeck()
print deck[:3] # [Card(rank='2', suit='spades'), Card(rank='3', suit='spades'), Card(rank='4', suit='spades')]
另外,仅仅实现了 getitem 方法,这一摞牌就变成可迭代的了
for card in deck:
print card
于是,in 运算符可以用在我们的 FrenchDeck 类上,因为它是可迭代的
print Card('Q', 'hearts') in deck # True
同时这个类还可以用于标准库中诸如random.choice、reversed 和 sorted 这些函数
② iter
import re, repr
RE_WORD = re.compile('\w+')
这个类可以迭代,因为实现了 iter 方法。
根据可迭代协议,iter 方法实例化并返回一个迭代器。
class Sentence:
def __init__(self, text):
self.text = text
self.words = RE_WORD.findall(text) # re.findall 函数返回一个字符串列表,里面的元素是正则表达式的全部非重叠匹配
def __repr__(self):
return 'Sentence(%s)' % repr(self.text) # .repr 这个实用函数用于生成大型数据结构的简略字符串表示形式
# 默认情况下,repr 函数生成的字符串最多有 30 个字符
# def __iter__(self):
# for word in self.words:
# yield word
# return # 这个 return 语句不是必要的;这个函数可以直接“落空”,自动返 回。
# # 不管有没有 return 语句,生成器函数都不会抛出 StopIteration 异常,而是在生成完全部值之后会直接退出
def __iter__(self):
return (match.group() for match in RE_WORD.finditer(self.text))
# 这里不是生成器函数了 (没有 yield),而是使用生成器表达式构建生成器,然后将其返回。
五、装饰器:Decorate
以函数名作为参数传递给装饰器,同时执行装饰器内部函数。
def clock2(func):
def clocked(*args, **kwargs):
result = func(*args, **kwargs)
name = func.__name__
arg_lst = []
if args:
arg_lst.append(', '.join(repr(arg) for arg in args))
if kwargs:
pairs = ['%s=%r' % (k, w) for k, w in sorted(kwargs.items())]
arg_lst.append(', '.join(pairs))
arg_str = ', '.join(arg_lst)
return 'The function %s has args:%s'%(name,arg_str),result
return clocked
@clock2
def snooze(name):
return 'welcome to my home, %s'%name
print snooze('regan') # ("The function snooze has args:'regan'", 'welcome to my home, regan')