拿到offer第一篇文章。最近的心路历程真TM的曲折,整个过程夢みたい、好像有些不切实际。。。。
这里是本书的第六章后面的内容。
第六章
1 enumerate
没啥说的,有时候挺方便的。
for i, item in enumerate(range(5)):
print(i, item)
2 关于切片
del lst[:] 清空列表, 相当于 lst.clear()
lst = [1, 2, 3, 4]
del lst[:] # 清空列表
print(lst)
3 迭代器
迭代器有__iter__, __next__方法
下面就是个无限循环的迭代器
class Repeater(object):
def __init__(self, value):
self.value = value
def __iter__(self):
return self
def __next__(self):
return self.value
repeater = Repeater('Hello')
for item in repeater:
print(item)
下面是带次数的迭代器
class BoundRepeater(object):
def __init__(self, value, max_repeats):
self.value = value
self.max_repeats = max_repeats
self.count = 0
def __iter__(self):
return self
def __next__(self):
if self.count >= self.max_repeats:
raise StopIteration
self.count += 1
return self.value
repeater = BoundRepeater('Hello', 3)
for item in repeater:
print(item)
生成器
生成器是简化版的迭代器
下面是无限生成器
def repeater(value):
while True:
yield value
for x in repeater("hi"):
print(x)
有限生成器
def bounded_repeater(value, max_repeater):
for i in range(max_repeater):
yield value
for i in bounded_repeater("hi", 3):
print(i)
生成器表达式
跟上面的有限生成器的效果是一样
iterator = ('Hello' for i in range(3))
for x in iterator:
print(x)
生成器表达式和列表解析式
listcomp = ['Hello' for i in range(3)]
genexpr = ('Hello' for i in range(3))
print(listcomp) # ['Hello', 'Hello', 'Hello']
print(genexpr) # <generator object <genexpr> at 0x00000194F3E627C8>
print(list(genexpr)) # ['Hello', 'Hello', 'Hello']
内联生成器表达式
遍历个生成器
for x in ('Bom dia' for i in range(3)):
print(x)
迭代器链
def integers():
for i in range(1, 9):
yield i
def squared(seq):
for i in seq:
yield i * i
def negated(seq):
for i in seq:
yield -i
chain = negated(squared(integers()))
print(list(chain))
# [-1, -4, -9, -16, -25, -36, -49, -64]
等价于下面的写法
integers = range(8)
squared = (i for i in integers)
negated = (-i for i in squared)
print(negated) # <generator object <genexpr> at 0x0000028D3E0A4570>
print(list(negated)) # [0, -1, -2, -3, -4, -5, -6, -7]
第七章 字典
1 字典的排序
这个返回的是列表套元组,
xs = {'a': 4, 'c': 3, 'b': 3, 'd': 1}
print(sorted(xs.items()
# [('a', 4), ('b', 3), ('c', 3), ('d', 1)] 返回的是列表套元组
下面是字典排序, key 参数
xs = {'a': 4, 'c': 3, 'b': 3, 'd': 1}
print(sorted(xs.items(), key=lambda x: x[1]))
# [('d', 1), ('c', 3), ('b', 3), ('a', 4)]
xs = {'a': 4, 'c': -3, 'b': 3, 'd': 1}
print(sorted(xs.items(), key=lambda x: abs(x[1])))
xs = {'a': 4, 'c': -3, 'b': 3, 'd': 1}
print(sorted(xs.items(), key=lambda x: abs(x[1]), reverse=True))
# [('a', 4), ('c', -3), ('b', 3), ('d', 1)]
2 下面的可就有些牛B了。 字典模拟 switch/case
一般的if elif
def dispatch_if(operator, x, y):
if operator == "add":
return x + y
elif operator == "sub":
return x - y
elif operator == "mul":
return x * y
elif operator == "div":
return x / y
用字典模拟的
def dispatch_dict(operator, x, y):
return {
'add': lambda: x + y,
'sub': lambda: x - y,
'nul': lambda: x * y,
'div': lambda: x / y,
}.get(operator, lambda: None)()
每次调用dispatch_dict() 都会为操作码查找创建一个临时字典和一串lamnda表达式,从性能看并不理想。可以先创建字典并将其作为常量,之后调用该函数时再引用字典。
3 “最疯狂”的字典表达式
书上是这么说的,其实还算让人一惊。。
a = {True: 'yes', 1: 'no', 1.0: 'maybe'}
print(a)
# {True: 'maybe'}
这里要注意的一点时, 在py中, py将bool视为int的子类。
就py而言, True, 1, 1.0 都表示相同的字典键。当解释器处理字典表达式时,会不断用后续的值覆盖True键的值。所以最后的
{True: 'maybe'} 值是maybe。
书上说“在研究CPython源码后, 我发现python的字典在键新值与键关联时不会自动更新新建对象。” 这也说明为什么
{True: 'maybe'} 的键是True。因为py将True, 1 , 1.0 哈希后发现是一个值, 就不会在更新键了。
4 合并字典的几种方式
首先想到的肯定是upadte啊
a = {"a": "A", "b": "B"}
c = {"c": "C", "b": "E"}
a.update(c)
print(a) # {'a': 'A', 'b': 'E', 'c': 'C'}
print(c) # {'c': 'C', 'b': 'E'}
利用 **,,,, 据说** 比update快
a = {"a": "A", "b": "B"}
c = {"c": "C", "b": "E"}
d = {**a, **c}
print(d) # {'a': 'A', 'b': 'E', 'c': 'C'}
第八章 py高效技巧
说是高效技巧, 其实也没啥。。。。
说说字节码
CPython解释器执行程序时, 首先将其翻译成一系列的字节码指令。字节码时Pyhon虚拟机的中间语言,可以提高程序的执行效率。
CPthon解释器不直接执行人类可读的源码,而是执行由编译器解析和语法语义分析产生的紧凑的数, 常量和引用。
这样再次执行相同的程序时能节省时间和内存,因为编译步骤产生的字节码会以.pyc和.pyo文件的形式缓存在磁盘上吗所以执行字节码比再次解析并执行相同的py文件速度更快。
def greet(name):
return 'Hello,' + name + '!'
print(greet.__code__.co_code) # b'd\x01|\x00\x17\x00d\x02\x17\x00S\x00' 指令
print(greet.__code__.co_consts) # (None, 'Hello,', '!') 常量
print(greet.__code__.co_varnames) # ('name',) 变量