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

 

posted @ 2020-03-28 18:36  天青色wy  阅读(236)  评论(0编辑  收藏  举报