Python3

1.上节内容回顾                                                                                                                                             

递归:

  • 明确的结束条件
  • 问题规模每递归一次都应该比上一次的问题规模有所减少
  • 效率低

高阶函数

文件:

rb、wb、ab

一般用在不同系统之间传数据,和传视频流的时候用到,一般以这种形式打开的需要制定encoding=‘utf-8’的字符编码形式

其他:

  • f.seek()
  • f.tell()
  • f.truncate()
  • f.flush() 

2.装饰器                                                                                                                                                     

 

 定义:装饰器本质是函数,(装饰其他函数)就是为其他函数添加附加功能

原则:

  • 不能修改被装饰的函数的源代码
  • 不能修改被装饰的函数的调用方式

言外之意就是说被装饰的函数在装饰器前都是完全透明的

实现装饰器知识储备:

  1. 函数即“变量”
  2. 高阶函数
      • 把一个函数名当做实参传给另外一个函数(不修改被装饰函数源代码的情况下为期添加功能)
      • 返回值中包含函数名(不修改函数的调用方式)

  3.嵌套函数

一、函数的调用顺序:函数就像变量一样,在定义的时候就是把函数体赋值给函数名这样子,Python在调用函数之前,该函数一定要先被声明

1 def foo():
2     print(foo)
3     bar()
4 foo()
5 def bar():
6     print(bar)
7 #报错,bar函数还未声明

 

 改正:

1 def foo():
2     print('foo')
3     bar()
4 def bar():
5     print('bar')
6 foo()
二、 高阶函数
1 def bar():
2     print 'in the bar'
3 def foo(func):
4     res=func()
5     return res
6 foo(bar)

三、嵌套函数

1 def foo():
2     def bar():
3         print 'in the bar'
4  
5     bar()
6  
7 foo()

 

四、装饰器

装饰器的语法以@开头,接着就是装饰器要装饰的函数的声明

装饰器就是一个函数,一个用来包装函数的函数,装饰器在函数声明完成的时候被调用,调用之后声明的函数被换成一个被装饰器装饰过后的函数。

当函数有形参时,在装饰的函数中也需要有相应的形参;

当原函数有return返回值时,在装饰的函数中也要萹蓄有return func(args);

函数参数固定:

1 def decorator(func):
2     def wrapper(n):
3         print('atarting')
4         func(n)
5         print('stopping')
6     return wrapper
7 def test(n):
8     print('in the test arg is %s'%n)
9 decorator(test)('alex')

函数参数不固定

1 def decorator(func):
2     def wrapper(*args,**kwargs):
3         print('starting')
4         func(*args,**kwargs)
5         print('stopping')
6     return wrapper
7 def test(n,x=1):
8     print('in the test arg is %s,he is %d'%(n,x))
9 decorator(test)('alex',x=2)

  1.无参装饰器

 1 import time
 2 def decorator(func):
 3     def wrapper(*args,**kwargs):
 4         start =time.time()
 5         func(*args,**kwargs)
 6         stop = time.time()
 7         print('run time is %s'%(stop-start))
 8     return wrapper
 9 @decorator  #test=decorator(test)
10 def test(list_test):
11     for i in list_test:
12         time.sleep(0.1)
13         print('_'*20,i)
14 test(range(10))

  2.有参装饰器

 1 import time
 2 def timer(timeout =0):
 3     def decorator(func):
 4         def wrapper(*args,**kwargs):
 5             start = time.time()
 6             func(*args,**kwargs)
 7             stop = time.time()
 8             print("run time is %s"%(stop-start))
 9             print(timeout)
10         return wrapper
11     return decorator
12 @timer(2)  #test=timer(2)(test)
13 def test(list_test):
14     for i in list_test:
15         time.sleep(0.1)
16         print('-'*20,i)
17 test(range(10))

高阶函数+嵌套函数=》装饰器

举一个复杂的例子:

 1 import time
 2 user,passwd = 'alex','abc123'
 3 def auth(auth_type):
 4     print("auth func:",auth_type)
 5     def outer_wrapper(func):
 6         def wrapper(*args, **kwargs):
 7             print("wrapper func args:", *args, **kwargs)
 8             if auth_type == "local":
 9                 username = input("Username:").strip()
10                 password = input("Password:").strip()
11                 if user == username and passwd == password:
12                     print("\033[32;1mUser has passed authentication\033[0m")
13                     res = func(*args, **kwargs)  # from home
14                     print("---after authenticaion ")
15                     return res
16                 else:
17                     exit("\033[31;1mInvalid username or password\033[0m")
18             elif auth_type == "ldap":
19                 print("搞毛线ldap,不会。。。。")
20 
21         return wrapper
22     return outer_wrapper
23 
24 def index():
25     print("welcome to index page")
26 @auth(auth_type="local") # home = wrapper()
27 def home():
28     print("welcome to home  page")
29     return "from home"
30 
31 @auth(auth_type="ldap")
32 def bbs():
33     print("welcome to bbs  page")
34 
35 index()
36 print(home()) #wrapper()
37 bbs()
View Code

 

 3.列表生成式,迭代器&生成器                                                                                                                                                   

生成器只有在调用时才会生成相应的数据

只记录当前的位置

只有一个__next__()方法,next()

列表生成式:

需求:将列表[0,1,2,3,4,5,6,7,8,9]将列表里的每个值加1、

三种写法:

1 a =[0,1,2,3,4,5,6,7,8,9]
2 b =[]
3 for i in a:
4     b.append(i+1)
5 a =b
6 print(a)
第一种
1 a = [1,2,3,4,5,6,7,8,9]
2 a =map(lambda x:x+1,a) #map(f(x),列表名)
3 for i in a:
4     print(i)
第二种
1 a= [i+1 for i in range(10)]
2 for i in a:
3     print(i)
第三种

第三种即就是列表生成式

生成器:

 通过列表生成式,我们可以直接创建一个列表,但是要创建100万个元素的列表,那么存储空间很庞大,因此,我们只需要生成式,它就是不必创建完整的list,从而节省大量空间,这种一遍循环一边计算的机制,称为生成器:generator

创建generetor有以下几种方法:

第一种:把列表生成式的[]改为(),就创建了一个generator

1 >>> L = [x * x for x in range(10)]
2 >>> L
3 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
4 >>> g = (x * x for x in range(10))
5 >>> g
6 <generator object <genexpr> at 0x1022ef630>

 

 此时g已经是一个生成器

如何一个个打印出来,用next()函数即可

 1 >>> next(g)
 2 0
 3 >>> next(g)
 4 1
 5 >>> next(g)
 6 4
 7 >>> next(g)
 8 9
 9 >>> next(g)
10 16
11 >>> next(g)
12 25
13 >>> next(g)
14 36
15 >>> next(g)
16 49
17 >>> next(g)
18 64
19 >>> next(g)
20 81
21 >>> next(g)
22 Traceback (most recent call last):
23   File "<stdin>", line 1, in <module>
24 StopIteration
View Code

 

generator保存的是算法,每次调用next(),就计算出g的下一个元素的值,直到计算出最后一个元素,没有更多的元素时,跑出StopIteration错误

不断调用next()方法太麻烦,因此用for循环,此种方法也不需要考虑StopIteration错误

 1 >>> g = (x * x for x in range(10))
 2 >>> for n in g:
 3 ...     print(n)
 4 ...
 5 0
 6 1
 7 4
 8 9
 9 16
10 25
11 36
12 49
13 64
14 81
View Code

 

 打印斐波拉契数列:

斐波拉契数列(Fibonacci):1, 1, 2, 3, 5, 8, 13, 21, 34, ...

1 def fib(max):
2     n,a,b=0,0,1
3     while n<max:
4         print(b)
5         a,b=b,a+b
6         n =n+1
7     return 'done'

 fib函数实际上定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑很类似generator。

要把fib()变成generator,只需要把print(b)改为yield(b)即可

1  def fib(max):
2       n,a,b=0,0,1
3       while n<max:
4           #print(b)
5           yield b   
6           a,b=b,a+b
7           n =n+1
8       return ‘done' 
>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>

generator,在每次调用next()执行,遇到yield就返回,再次执行则从上次返回的yield语句处继续执行

data = fib(10)
print(data)

print(data.__next__())
print(data.__next__())
print("干点别的事")
print(data.__next__())
print(data.__next__())
print(data.__next__())
print(data.__next__())
print(data.__next__())

#输出
<generator object fib at 0x101be02b0>
1
1
干点别的事
2
3
5
8
13

在循环过程中不断调用yield,就会不断中断,当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。

把函数变成generator之后,基本不会用next()来获取下一个返回值,而是直接使用for循环来迭代:

1 >>> for n in fib(6):
2 ...     print(n)
3 ...
4 1
5 1
6 2
7 3
8 5
9 8

在用for循环调用generator时,发现拿不到generator的return语句的返回值,如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:

 1 >>> g = fib(6)
 2 >>> while True:
 3 ...     try:
 4 ...         x = next(g)
 5 ...         print('g:', x)
 6 ...     except StopIteration as e:
 7 ...         print('Generator return value:', e.value)
 8 ...         break
 9 ...
10 g: 1
11 g: 1
12 g: 2
13 g: 3
14 g: 5
15 g: 8
16 Generator return value: done

还可以使用yield实现单线程的情况下并发运算的效果

 1 #_*_coding:utf-8_*_
 2 __author__ = 'Alex Li'
 3 
 4 import time
 5 def consumer(name):
 6     print("%s 准备吃包子啦!" %name)
 7     while True:
 8        baozi = yield
 9 
10        print("包子[%s]来了,被[%s]吃了!" %(baozi,name))
11 
12 
13 def producer(name):
14     c = consumer('A')
15     c2 = consumer('B')
16     c.__next__()
17     c2.__next__()
18     print("老子开始准备做包子啦!")
19     for i in range(10):
20         time.sleep(1)
21         print("做了2个包子!")
22         c.send(i)
23         c2.send(i)
24 
25 producer("alex")
26 
27 #通过生成器实现协程并行运算

迭代器:

直接作用于for循环的数据类型以下几种:

一类是集合数据类型:列表(list),元组(tuple),字典(dict),集合(set),字符串(str)等

一类是generator,包括生成器和带yield的generator function。

这类可直接作用于for循环的对象统称为可迭代对象:Tterable

可以使用isinstance()判断一个对象是是否是Iterrator对象:

 1 >>> from collections import Iterable
 2 >>> isinstance([], Iterable)
 3 True
 4 >>> isinstance({}, Iterable)
 5 True
 6 >>> isinstance('abc', Iterable)
 7 True
 8 >>> isinstance((x for x in range(10)), Iterable)
 9 True
10 >>> isinstance(100, Iterable)
11 False

而生成器不但可以作用于for循环,还可以被next()函数不断调用并但会下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

可以被next()函数调用并不断返回下一值的对象称为迭代器:Iterator

可以使用isinstance()判断一个对象是否是Iterator对象:

1 >>> from collections import Iterator
2 >>> isinstance((x for x in range(10)), Iterator)
3 True
4 >>> isinstance([], Iterator)
5 False
6 >>> isinstance({}, Iterator)
7 False
8 >>> isinstance('abc', Iterator)
9 False

由此可知:生成器都是Iterator对象,但列表、字典、字符串虽然是Iterable但不是Iterator

小结:

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,他们表示一个惰性极端的序列(即只有在需要的时候才会计算,不需要则不会计算);

集合数据类型如:列表、字典、字符串,集合等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

如for新欢本质上是通过不断调用next()函数实现的:

 for x in [1, 2, 3, 4, 5]: pass 

实际上等价于:

 1 # 首先获得Iterator对象:
 2 it = iter([1, 2, 3, 4, 5])
 3 # 循环:
 4 while True:
 5     try:
 6         # 获得下一个值:
 7         x = next(it)
 8     except StopIteration:
 9         # 遇到StopIteration就退出循环
10         break

4.内置函数                                                                                                                                                           

 见博客地址:

5.软件目录结构规范                                                                                                                                               

 

posted on 2016-12-20 22:52  cicialia  阅读(279)  评论(0编辑  收藏  举报

导航