错题整合(1)
错题整合
1 读取文件最后一行
f = open('file_modify.txt', 'rb') offset = -10 while True: f.seek(offset, 2) if len(f.readlines()) > 1: print(f'最后一行是{f.readlines()[-1].decode("utf-8")}') break offset *= 2
解析:
先估算最后一行的大概长度,然后根据最后seek方法从最后位置往前定光标位置,首先光标位置给小一点,再根据f.readline()读取内容,判断读取内容是否有一行,没有一行的话,加大偏移位置,有一行的读取出来,并break。
2 判断下面代码运行的结果。
 
def extendList(val,list=[]): list.append(val) return list list1 = extendList(10) list2 = extendList(123,[]) list3 = extendList('a') print('list1=%s'%list1) print('list2=%s'%list2) print('list3=%s'%list3) 运行结果: list1=[10, 'a'] list2=[123] list3=[10, 'a']
解析:
函数参数中如果默认参数定义了空列表,如果函数第一次调用中使用了默认的空列表,函数体对这个列表进行修改,第二次调用的参数还是用默认空列表时,此时的列表是之前调用时修改后的列表,也就不是默认的空列表。
如果第二次调用给定参数是空列表,而不是使用默认的空列表,则此时对列表修改用的是传入的空列表参数。
3 迭代器只能迭代一次,判断下面代码运行的结果?
 
def g_test(): """定义一个生成器""" for i in range(4): yield i t = g_test() for i in t: print(i) # 结果:0,1,2,3 t_g = (i for i in t) print(list(t_g)) # 结果:[]
解析:t = g_test() 获取了一个生成器函数产生的一个迭代器对象,但是t里面没有任何值,使用for循环是对t使用.__next__()方法执行迭代器对象,获取返回的值。因为for已经对迭代器遍历完了,而迭代器只能遍历一次所以当t_g生成器表达式再次遍历t时,什么也没有遍历到,得到的t_g是个空的迭代器,用list转换后得到一个空列表。
4 生成器表达式内在运行机制,和list运行机制。
 
def g_test(): """定义一个生成器""" for i in range(4): yield i t = g_test() t1 = (i for i in t) t2 = (i for i in t1) print(list(t1)) print(list(t2)) # 运行结果 # [0, 1, 2, 3] # []
解析:
生成器返回的是一个迭代器对象,但是有三点需要注意:第一个是迭代器只能遍历一次;第二个,生成器在复制给变量时,并没有运行调用执行迭代器。第三个,对象迭代器对象并不是一个容器类型的数据,本身并没有任何值,而是根据next方法依次取值。
本题中,在表达式t1=(i for i in t)时,生成器表达式只是生成了一个迭代器对象,并没有调用生成器执行,所以这一步也没有遍历t,同理t2=(i for i in t1)也没有遍历t1。当知道list(t1)时,list开始
5 求下面代码运行结果
 
v = [lambda :x for x in range(10)] print(v) print(v[0]) print(v[0]())
解析:
[lambda :x for x in range(10)]是一个列表推导式,等效于下面代码
v = [] for x in range(10): def func(): return x v.append(func)
因为for循环了10次,所以列表v中生成了10个函数,都是func,内部代码都是return x,但是都没有调用,当取出第一个函数调用时,for循环已经完成,x的值已指向9存在全局。函数func没有参数传入,所以去全局找x返回,所以返回的是9。对内部所有函数都是这样,调用的时候取得值都是9.
6 求下面代码运行结果
 
v = (lambda :x for x in range(10)) print(v) # 生成器 print(v[0]) # 报错 print(v[0]()) # 报错 print(next(v)) # 第一个函数的内存地址 print(next(v)()) # 1,第二个函数调用,此时x=1,所返回1
解析:
首先 (lambda :x for x in range(10))就是一个生成器表达式,赋值给v,所以v就是一个生成器,所以v[0]和v[0]()会报错,但是这个时候的生成器仅仅只是一个生成器,没有next取值,通过next取值,获取的是当x=0的时候,生成器返回的lambda : x函数,所以next(v)返回的是一个匿名函数的地址,注意,此时生成器是驻留的状态,x是0并没有在for中累加。当我们又一次使用next(v)()时,已经是第二次next取值,此时我们获取的是当x=1的时候,生成器返回的lambda : x函数,然后对匿名函数调用,传入参数1,所以打印的结果是1。

 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号