python学习笔记整理(二)
2 # 迭代
3 '''
4 # 能够通过for循环来遍历的对象,是可迭代对象Iterable。包括两类:
5 # 1、集合数据类型:list,tuple,dict,set,str
6 # 2、生成器和带 yield 的generator function。
7
8 # 可以使用 isinstance() 判断一个对象是否是 Iterable 对象:
9
10 from collections import Iterable
11 a = isinstance([666],Iterable)
12 print(a) # True
13
14 # 字典的迭代
15 d = {'a':1,'b':2,'c':3}
16 for key in d:
17 print(key) # a b c
18
19 for value in d.values():
20 print(value) # 1 2 3
21
22 for x,y in [('a',1),('b',2),('c',3)]:
23 print(x,y)
24
25 # a 1
26 # b 2
27 # c 3
28
29 # 练习:使用迭代查找一个list中最小和最大值,并返回一个tuple:
30 l = [2,4,3,6,9]
31
32 def findMinAndMax(L):
33 if len(L) == 0:
34 return (None, None)
35
36 minValue = L[0]
37 maxValue = L[0]
38
39 for x in L:
40 if x < minValue:
41 minValue = x
42 elif x > maxValue:
43 maxValue = x
44 return (minValue, maxValue)
45
46
47 print(findMinAndMax(l))
48
49 # ------------------------------------------------------------------------
50 # 生成器 generator
51
52 # 需要的时候才生成数据,不要的时候不需要生成数据。这种一边循环一边计算的机制称为生成器。
53 # 创建生成器的方法:
54 # 1、把列表生成式的[]改成() :
55
56 g = (x*x for x in range(10))
57 # 通过next()函数获得generator的下一个返回值
58 print(next(g)) #0
59 print(next(g)) #1
60 print(next(g)) #4
61 # 生成器是可迭代对象,可用for循环取值
62 for i in g:
63 print(i)
64 # 2、通过yield关键字创建generator
65
66 def fib(max):
67 n, a, b = 0, 0, 1
68 while n < max:
69 print(b)
70 a, b = b, a + b # 后面是个元组
71 n = n + 1
72 return 'done'
73 fib(6) # 112358
74
75
76 # 把上面的fib()函数print(b)改为yield(b),就变成了生成器函数。
77 def fib(max):
78 n, a, b = 0, 0, 1
79 while n < max:
80 yield b
81 a, b = b, a + b # 后面是个元组
82 n = n + 1
83 return 'done'
84
85 # 每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
86 f = fib(6) # 调用一个生成器函数,返回的是一个迭代器对象。
87 print(next(f)) # 1
88 print(next(f)) # 1
89 print(next(f)
90 print(next(f)) # 3
91 # 直接for遍历
92 for i in f:
93 print(i) # 112358
94
95
96
97 练习:通过生成器用列表的形式输出杨辉三角中的每一行
98 # 1
99 # 1 1
100 # 121
101 # 1331
102 '''
103
104 def tri():
105 arr = [1]
106 n=0
107 while n<=5:
108 yield arr
109 arr = [1] + [arr[i] + arr[i + 1] for i in range(len(arr) - 1)] + [1]
110 n+=1
111
112 print(next(tri())) # [1]
113 print(next(tri())) # [1]
114 print(next(tri())) # [1]
115 print(next(tri())) # [1]
116 # 很奇怪,这里用next()函数为什么总是输出[1]
117 print(list(tri()))
118 for i in tri():
119 print(i)
120
121 # [1]
122 # [1, 1]
123 # [1, 2, 1]
124 # [1, 3, 3, 1]
125 # [1, 4, 6, 4, 1]
126 # [1, 5, 10, 10, 5, 1]
127
128
129 # 生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,
130 # 直到最后抛出StopIteration错误表示无法继续返回下一个值了。
131
132 from collections import Iterator,Iterable
133 print(isinstance(tri(),Iterator)) # True
134 print(isinstance([],Iterator)) # False
135 print(isinstance('abcd',Iterator)) # False
136 print(isinstance(iter('abcd'),Iterator)) # True
137
138 # ------------------------------------------------------------------------
139 # send()函数
140 def test():
141 i=1
142 while i<5:
143 temp = yield i
144 print(temp)
145 i+=1
146 t=test()
147 print("-------------------------------")
148 print(next(t)) # 1
149 print(next(t)) # None 2
150 print(next(t)) # None 3
151 t.send("666") # 把值666替换程序停止的位置,即temp=666
152
153 # print(next(t)) # None,StopIteration
154 # 注意:send()在生成器函数创建完后在next之前就调用,此时只能传值None,否则报错;
155
156 # yield要配合循环使用才有意义
157 def test():
158 i=1
159 yield i
160 i+=1
161 print(i)
162 t=test()
163 print(next(t)) # 1
164 # print(next(t)) # 2 StopIteration
165
166
167
168 # 总结:
169 # 1、生成器都是可迭代对象;
170 # 2、生成器都是迭代器对象;
171 # 3、凡是可作用于for循环的对象都是Iterable可迭代对象;
172 # 4、凡是可作用于 next()函数的对象都是Iterator迭代器对象;
173 # 5、list,dict,str等数据类型可通过 iter()函数变为迭代器对象;
174
175
176
177 # ------------------------------------------------------------------------
178 # 循环实现阶乘
179
180 def jie(n):
181 s=1
182 for i in range(1,n+1):
183 s = s*i
184 print(s)
185 jie(5) # 120
186
187 #递归实现阶乘
188 def jie2(n):
189 if n==1:
190 return 1
191 else:
192 return n*jie2(n-1)
193 print(jie2(6)) # 720
194
195
196 # 1,1,2,3,5,8,13递归实现斐波那契数列
197 def fib(n):
198 if n==1 or n==2:
199 return 1
200 else:
201 return fib(n-1)+fib(n-2)
202
203 print(fib(6)) # 8
204
205
206 # 100元买100本书,A书5/本,B书3/本,C书0.5/本,共有几种买法?
207 def exa1():
208 for i in range(21):
209 for j in range(34):
210 if 5*i+3*j+0.5*(100-i-j)== 100:
211 print('%s,%s,%s'%(i,j,100-i-j))
212
213 exa1()
214 # 0,20,80
215 # 5,11,84
216 # 10,2,88
217
218
219 # ------------------------------------------------------------------------
220
221 # 内置函数:
222
223 # filter(函数,可迭代对象):根据函数返回的布尔值决定是否将可迭代对象中的元素
224 # 添加到新的列表
225 def fun1(n):
226 return n<5
227 li = [1,2,3,4,5,6,7,8,9]
228 a = filter(fun1,li)
229 print(list(a)) # [1, 2, 3, 4]
230
231 # map(函数,可迭代对象):对可迭代对象中的元素做处理后放到新列表
232 def fun2(n):
233 return n*n
234 a=map(fun2,li)
235 print(list(a)) #[1, 4, 9, 16, 25, 36, 49, 64, 81]
236
237 # zip() 函数用于将可迭代的对象作为参数,
238 # 将对象中对应的元素打包成一个个元组,然后返回一个迭代器对象。
239 a = zip([1,2,3],['a','b','c'])
240 print(type(a))
241 print(isinstance(a,Iterator)) # True
242 print(isinstance(a,Iterable)) # True
243 print(list(a))
244 for i in a:
245 print(i)
246
247
248 def fun(x):
249 a=x
250
251 # print(fun(3).a)
252
253 class test(object):
254 def __init__(self):
255 num = 1
256 def haha(self):
257 print("haha")
258
259 print(id(test))
260 print(type(test))
261 print(id(test()))
262 print(type(test()))
263
264
265 # python中的type和object
266 # 注意:我们通常在python中称对象为object,但是python中有个基类也叫object
267 # 这两个东西不能混淆。当然,基类object也是一个对象,即python中一切皆对象,
268 # 它是type的实例对象。type是谁呢?type继承自object这个基类,它也是一个类。
269 # 这就让人有点糊涂了,
270
271 class nt(object):
272 print("haha")
273
274 i = int('1')
275
276 print(i)
277
278 # ------------------------------------------------------------------------
279
280 # 闭包
281 # 在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,
282 # 那么将这个函数以及用到的一些变量称之为闭包
283 def fun(num1):
284 def fun_in(num2):
285 return num1+num2
286 return fun_in
287
288 a = fun(100)
289 print(a(200)) # 300
290 print(a(1)) # 101
291
292 # ------------------------------------------------------------------------
293
294 # 装饰器
295 # 假如有个需求,用户在调用登陆函数之前要验证用户信息是否正确,
296 # 验证通过后才能登陆。这用装饰器可以实现,在调用登陆函数的时候
297 # 自行调用验证函数。
298 #
299 def check(fun):
300 ''' 验证函数 '''
301 def check_in():
302 print("正在验证用户信息。。。")
303 if True:
304 print("验证通过!")
305 return fun()
306 else:
307 print("验证失败!")
308 return check_in
309
310 @check # 相当于: fun = check(fun)
311 def fun():
312 ''' 登陆函数 '''
313 print("正在登陆。。。")
314
315 fun()
316 # 正在验证用户信息。。。
317 # 验证通过!
318 # 正在登陆。。。
319
320
321 # 注意:在调用被装饰函数之前,装饰器函数就已经执行了。
322
323
324 def check(fun):
325 ''' 验证函数 '''
326 print("这是一个装饰器函数!")
327 def check_in():
328 print("正在验证用户信息。。。")
329 if True:
330 print("验证通过!")
331 return fun()
332 else:
333 print("验证失败!")
334 return check_in
335
336 @check # python解释器在执行到这里时,就会执行check(fun),打印上面那句话
337 def fun():
338 ''' 登陆函数 '''
339 print("正在登陆。。。")
340
341 # 结果:
342 # 这是一个装饰器函数!
343
344
345
346 # 多个装饰器嵌套
347
348 def d1(f):
349 print("==============d1===============")
350 def inner1():
351 print("------inner1-------")
352 return "<d1>" + f() + "<d1>"
353 return inner1
354
355
356 def d2(f):
357 print("==============d2===============")
358
359 def inner2():
360 print("------inner2-------")
361 return "<d2>" + f() + "<d2>"
362 return inner2
363
364 @d1 # f = d1(f)
365 @d2 # f = d2(f)
366 def f():
367 print("------3-------")
368 return 'haha'
369
370 print(f())
371
372 '''
373 结果是:
374 ==============d2===============
375 ==============d1===============
376 ------inner1-------
377 ------inner2-------
378 ------3-------
379 <d1><d2>haha<d2><d1>
380 '''
381
382 # 相当于:把下层装饰器的结果作为参数传给上层装饰器
383 # f=d1(d2(f))
384 # f()
385 # 就像淘宝卖家寄快递一样,比如买了个水杯,装饰器装饰的过程就是打包水杯的过程,先给水杯套上一个
386 # 纸盒子,再将纸盒子外面包一层泡沫,然后放到一个大快递盒子里,贴上发件信息。
387 # 对应的是:先打印d2,再打印d1;
388
389 # 调用函数的时候就如同买家收到包裹后,先撕开外面的盒子,再扯掉泡沫,再撕掉里面的纸盒子,取出水杯。
390 # 对应的是:-------inner1------、-------inner2-------、-----3-------
391
392
393
394 # 定长参函数:
395 def d(func):
396 def d_in(a,b):
397 func(a,b)
398 return d_in
399
400 @d
401 def func(a,b):
402 print("a+b的值是:%d"%(a+b))
403
404
405 func(1,2)
406
407 # a+b的值是:3
408
409
410 # 不定长参函数:
411 def d(func):
412 def d_in(a,b,*c,**d): #1、把3,4,5放在元组c里,此时c=(3,4,5)
413 print("c =",c)
414 print("haha")
415 func(a,b,*c,**d) #2、给c解包成3,4,5后传到func里
416 return d_in
417
418 @d
419 def func(a,b,*tun,**dic): #3、 将收到的3,4,5放到元组tun里
420 print("a=%d"%a)
421 print("b =",b)
422 print("tun={0}".format(tun))
423 print("dic={0}".format(dic))
424
425
426 func(1,2,3,4,5,name="wy",age=18)
427
428 '''
429 结果:
430 c = (3, 4, 5)
431 haha
432 a=1
433 b = 2
434 tun=(3, 4, 5)
435 dic={'name': 'wy', 'age': 18}
436
437 '''
438
439 # 有返回值函数装饰:
440
441 def d(func):
442 def d_in(a,b):
443 print("该干嘛干嘛1")
444 result = func(a,b)
445 print("该干嘛干嘛2")
446 return result
447 return d_in
448
449 @d
450 def func(a,b):
451 print("该干嘛干嘛3")
452 return "a+b的值是:%d"%(a+b)
453
454 a = func(1,2)
455 print(a)
456
457 '''
458 结果:
459 该干嘛干嘛1
460 该干嘛干嘛3
461 该干嘛干嘛2
462 a+b的值是:3
463 '''
464
465 # 装饰器带参数:
466 # 装饰器如果带参数,则先执行@后面的函数,返回得到真正的装饰器函数
467 def func1(a):
468 def func2(func):
469 def func3():
470 print("a =",a)
471 func()
472 return func3
473
474 return func2
475
476 @func1("666") # 等价于 @func2
477 def func():
478 print("haha")
479
480 func()
481
482 # a = 666
483 # haha
484
485 # 类装饰器
486
487 class Test(object):
488 def __init__(self,func):
489 print("---正在初始化---")
490 print("func name is %s"%func.__name__)
491 self.__func = func
492 def __call__(self):
493 print("---装饰器中的功能---")
494 self.__func()
495
496 @Test # 等价于 test = Test(test)
497 def test():
498 print("---test---")
499
500 test()
501
502 '''
503 结果:
504 ---正在初始化---
505 func name is test
506 ---装饰器中的功能---
507 ---test---
508 '''
509
510 # 注意:在类里面写上__call__方法,则在调用类的对象时直接调用call方法。
511 # 类装饰器的原理跟函数装饰器完全一样。
512
513
514
515 # ------------------------------------------------------------------------
516 # python给类动态添加方法
517 class Person(object):
518 def __init__(self,name,age):
519 self.name = name
520 self.age = age
521
522 def eat(self): # 这里的self自动传入p对象
523 print("======%s正在吃======="%self.name)
524
525 def run(self):
526 print("======%s正在跑======="%self.name)
527
528 p = Person("wy",18)
529 p.eat()
530 p.run = run
531 # p.run() 报错,给类添加方法时并未将对象p传给run中的self
532 # 成功调用run的两种方式:
533 # 1:直接传入对象参数
534 p.run(p)
535 # 2:绑定方法到对象
536 import types
537 p.run = types.MethodType(run,p)
538 p.run()
539
540
541
542 # 给类添加类方法和静态方法
543 # 给类添加方法就比给对象添加方法简单些,直接 类名.方法名=方法名
544 @classmethod
545 def fun1(cls):
546 print("=======class method ========")
547
548 @staticmethod
549 def fun2():
550 print("=======static method ========")
551
552
553 Person.fun1 = fun1
554 Person.fun1() #=======class method ========
555
556 Person.fun2 = fun2
557 Person.fun2() #=======static method ========
558
559
560 # __slots__变量
561 # 如上,python允许动态的给类添加属性,但如果要限制实例的属性怎么办,只允许
562 # 添加指定的属性。
563
564 class P(object):
565 __slots__ = ("name")
566
567
568 p = P()
569 p.name = "wy"
570 print(p.name) # wy
571
572 # p.age = 18
573 # print(p.age) # AttributeError
574
575
576
577 # 元类
578
579 # 常规方法创建类:
580 class Test:
581 num = 100
582 def __init__(self):
583 self.name = "wy"
584 def pri(self):
585 print(self.num)
586 t=Test()
587 t.pri() # 100
588
589 print(t.name) # wy
590
591 # 在这里,实例对象t是由类Test创建的,而类Test是由类type创建的。
592 # 如下,类type创建了继承自Test的、拥有属性num2的实例对象————类Test2。
593
594 Test2 = type("Test2",(Test,),{"num2":200})
595 print(Test2.num2) # 200
596 Test2().pri() # 100 继承了pri方法,通过实例对象调用
597 print(type(Test2)) # <class 'type'>
598 print(type(t)) # <class '__main__.Test'>
599 print(type(Test)) # <class 'type'>
600
601 # 这里的type类就是元类。
602
603
604 # GC垃圾回收机制
605 # 以引用计数为主,以隔代回收为辅
606
607 # 引用计数
608 # 当一个对象的引用计数为0时,该对象在系统中所占的内存就会被释放。
609 # 当出现循环引用的时候,两个对象相互引用对方,引用计数都为1,此时
610 # 会使用隔代回收机制将引用计数减去1变为0后再释放内存。
611 # sys.getrefcount()查看引用计数,引用计数+1后又被-1
612 class Ref(object):
613 def __init__(self,value):
614 self.value = value
615
616
617 r1 = Ref("liudehua")
618 r2 = Ref("gutianle")
619 import sys
620 print(sys.getrefcount(r1)) # 2
621 r1.next = r2
622 r2.pre = r1
623 print(sys.getrefcount(r1)) # 3
624
625 r1 = None
626 r2 = None
627
628
629 import gc
630 print(gc.get_threshold()) # (700, 10, 10)
631 # 700:当新创建的对象个数减去新释放的对象数后存在的个数大于700则启动零代回收。
632 # 10:每清理10次零代链表就清理一次一代链表;
633 print(gc.get_count()) #(331, 3, 1) 目前的清理情况
634
635 # gc.gisable() 关闭垃圾回收机制
636 # gc.enable() 打开垃圾回收机制
637 # gc.colletc() 手动调用垃圾回收机制
638 #
639 # 导致引用计数+1的情况:
640 # 1、对象被创建,a="zhangwenwen";
641 # 2、对象被引用,如b=a;
642 # 3、对象作为实参传入到函数中,如func(a)。函数执行完毕后-1
643 # 4、对象作为一个元素存储在容器中,如list=[a]。列表销毁或元素被删除则-1