第二十章 迭代和解析
2017-04-12 19:41 szn好色仙人 阅读(157) 评论(0) 编辑 收藏 举报#1. #A:列表解析在一个序列的值上应用一个任意表达式,将其结果收集到一个新的列表中并返回 #B:map是一个迭代器,根据需求产生结果,同样为了节省内存,列表解析被编码成生成器表达式 def Fun(x) : return x ** 2 L0 = [1, 2, 3] L1 = [x ** 2 for x in L0] #L1 = [1, 4, 9] L2 = [Fun(x) for x in L0] #L2 = [1, 4, 9] L3 = [(x , y) for x in L0 if x % 2 == 0 for y in L1 if y % 2 == 1] #L3 = [(2, 1), (2, 9)] L4 = list(x ** 2 + 1 for x in L0) #L4 = [2, 5, 10] #2.有两种语言会尽可能的延迟结果创建 #A:生成器函数:编写为常规的def语句,但是使用yieled语句一次返回一个结果,在每个结果之间挂起和继续他们的状态 #B:生成器表达式:每次按需产生结果的一个对象 #3. #A:生成器函数和常规函数之间的主要代码不同之处在于,生成器yields(产生)一个值,而不是返回一个值,yield语句挂起该函数并向调用者发送一个值,但是保留足够的状态以使得函数能够从它离开的地方继续 #B:当继续时候,函数在上一个yield返回后立即继续执行,从函数角度来看,这允许其代码随时间产生一系列值,而不是一次计算它们并在诸如列表的内容中返回它们 #C:函数包含一条yield语句,该语句特别编译为生成器。当调用时,它们返回一个迭代器对象,支持__next__来进行自动创建。 #D:生成器函数也可能有一条return语句,总是在def语句块的末尾,直接终止值的生成 #E:生成器函数和生成器表达式自生都是迭代器,并只支持一次活跃的迭代,我们无法同时拥有位于不同位置的多个迭代器 def fun(n): for i in range(n): yield i ** 2 fun_3 = fun(3) value = fun_3.__next__ #value = <method-wrapper '__next__' of generator object at 0x0000000002B0D558> n0 = value() #n0 = 0 n1 = fun_3.__next__() #n1 = 1 n2 = fun_3.__next__() #n1 = 4 try: n2 = fun_3.__next__() except StopIteration: pass #执行至此 fun_it0 = fun(3) fun_it1 = fun(3) b0 = iter(fun_3) is fun_3 #b0 = True b1 = fun_it0 == fun_it1 #b1 = False #4. #A:从语法上讲,生成器表达式就像一般的列表解析一样,但是它们是括在圆括号中而不是方括号中,返回一个生成器对象,这个对象支持迭代 it= (x * 2 for x in 'szn') L0 = [] for v in it: L0.append(v) #L0 = ['ss', 'zz', 'nn'] #5. #A:zip L0 = list(zip("szn")) #L0 = [('s',), ('z',), ('n',)] L0 = list(zip("szn", ())) #L0 = [] def myMap0(fun, *seqs): res = [] for arg in zip(*seqs): #注意这里是*seqs而不是seqs,这里对seqs进行了解包 res.append(fun(*arg)) return res def fun(x): return x + ['szn'] L0 = myMap0(fun, [[1, 2, 3], [4, 5, 6, 7]]) #L0 = [[1, 2, 3, 'szn'], [4, 5, 6, 7, 'szn']] L0 = myMap0(fun, [[1, 2, 3], [4, 5, 6, 7], [8]]) #L0 = L0 = [[1, 2, 3, 'szn'], [4, 5, 6, 7, 'szn'], [8, 'szn']] L0 = myMap0(lambda x, y : x + y, [1, 2, 3], [4, 5, 6, 7]) #L0 = [5, 7, 9] L0 = myMap0(lambda x : x + 1, [1, 2]) #L0 = [2, 3] L0 = list(zip(*([1, 2, 3], [4, 5, 6, 7]))) #L0 = [(1, 4), (2, 5), (3, 6)] L1 = list(zip(([1, 2, 3], [4, 5, 6, 7]))) #L1 = [([1, 2, 3],), ([4, 5, 6, 7],)] def fun(v, v1):return v, v1 v = fun(*([1, 2, 3], [4, 5, 6, 7])) #v = ([1, 2, 3], [4, 5, 6, 7]) def myMap1(fun, *seqs): return [fun(*args) for args in zip(*seqs)] L0 = myMap1(lambda x, y : x + y, [1, 2, 3], [4, 5, 6, 7]) #L0 = [5, 7, 9] def myMap2(fun, *seqs): res = [] for args in zip(*seqs): yield fun(*args) L0 = list(myMap1(lambda x, y : x + y, [1, 2, 3], [4, 5, 6, 7])) #L0 = [5, 7, 9] def myMap3(fun, *seqs): return (fun(*args) for args in zip(*seqs)) L0 = list(myMap3(lambda x, y : x + y, [1, 2, 3], [4, 5, 6, 7])) #L0 = [5, 7, 9] #6. #A: L0 = [1, 2, 3] it = iter(L0) it1 = iter(it) bValue = it is it1 #bValue = True list(it) bValue = bool(it) #bValue = True L1 = [] bValue = bool(iter(L1)) #bValue = True def fun(args): it = iter(args) while 1: value = it.__next__() yield value value = list(fun([1, 2, 3])) #value = [1, 2, 3] #8. #A:!!!!!!!!!!!!!!!!!待研究 def FunA(*args): it = map(iter, args) while 1: it1 = it.__next__() #问题一:这里进行的迭代不会引发StopIterator异常吗 while 1: try: value = it1.__next__() print("") yield value except: break value0 = list(FunA([1, 2], ['a', 'b', 'c'])) #value0 = [1, 2, 'a', 'b', 'c'] 问题二:为什么这里value0 = [1, 2, 'a', 'b', 'c'] def FunB(*args): it = map(iter, args) while 1: it1 = it.__next__() while 1: value = it1.__next__() print("") yield value value1 = list(FunB([1, 2], ['a', 'b', 'c'])) #value1 = [1, 2] 问题三:为什么这里value1 = [1, 2] #9.!!!!!!!!!!!!!!!!!待研究 def myzipA(*args): iters = list(map(iter, args)) while iters: res = [next(i) for i in iters] yield tuple(res) value = list(myzipA('abc', 'efg')) #value = [('a', 'e'), ('b', 'f'), ('c', 'g')] ''' def myzipB(*args): iters = map(iter, args) while iters: res = [next(i) for i in iters] yield tuple(res) value = list(myzipB('abc', 'efg')) ''' #10. #A:time.time()返回1970年至今的秒计数 #B:time.clock()在Unix 中,将当前的处理器时间以浮点数的形式返回,单位为秒。它的精确度(准确地说是“处理器时间”的精确度)取决于同名的C函数,无论如何,这个函数是python关于时间计算的标尺。 # WINDOWS中,第一次调用,返回的是进程运行的实际时间。而第二次之后的调用是自第一次调用以后到现在的运行时间。(实际上是以WIN32上QueryPerformanceCounter()为基础,它比毫秒表示更为精确 #C:time.sleep()设置休眠的秒数 import time t = time.time() #t = 1491912888.716247 t0 = time.clock() time.sleep(1) t1 = time.clock() - t0 #t1 = 0.9995179215014475 #11. #A: import sys str = sys.platform #str = 'win32' #12. #A:函数陷阱 value = 10 def funA(): print(value) #运行到这里的时候会出错 value = 2 #产生上述错误的原因在于:被赋值的变量名在函数内部被当做本地变量对待,而不是仅仅在赋值以后的语句才被当做是本地变量,所以所执行的print语句中使用了未定义的本地变量名 def funB(): global value print(value) #正常运行 value = 1 #全局变量value被更改了 def funC(): import __main__ list = dir(__main__) #list = ['Fun', 'FunA', 'FunB', 'L0', 'L1', 'L2', 'L3', 'L4', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', ...] print(__main__.value) #输出的是全局变量value value = 1 #不会修改全局变量value #13 #A:模块是对象,并且所有的模块都有一个内置属性 __name__。一个模块的 __name__ 的值取决于您如何应用模块。如果 import 一个模块,那么模块__name__ 的值通常为模块文件名, # 不带路径或者文件扩展名。但是您也可以像一个标准的程序样直接运行模块,在这种情况下, __name__ 的值将是一个特别缺省"__main__" ''' Test.py内容: def FunTest20(): return __name__ ''' import Test str = Test.FunTest20() #str = 'Test' str1 = __name__ #str1 = '__main__' #14. #A:默认参数是在def语句运行时评估并保存的,而不是在函数调用时。从内部讲,python会将每个默认参数保存成一个对象,附加在这个函数本身 valueTest = 10 def FunTest(value = []): value.append(1) return value value0 = FunTest() #value0 = [1] value1 = FunTest() #value1 = [1, 1] bValue = value0 is value1 #bValue = True