Python从零开始之Day4

高阶函数

变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

1 def test1(a,b,c):
2     print(c(a)+c(b))
3 
4 test1(-1,-4,abs)              #把另一个函数当做参数
高阶函数
1 a   =   lambda    x    :   x*3        #只能写一行,中间不能再加更多的参数,只能进行简单的操作
2 
3 #可以写三元运算
4 b = lambda y:4if y < 10 else y
匿名函数

 

装饰器

装饰器:

1、不修改被装饰函数源代码

2、本身就是一个函数

3、与被装饰函数本身无关,不影响其运行

实现装饰器知识储备:

1、函数既变量

2、高阶函数

3、函数嵌套

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

 1 import time
 2 def aaa(x):                       #运用高阶函数和函数的嵌套实现装饰器
 3     def test(*args,**kwargs):        #记得写参数,避免有参数是运行出错
 4         start_time = time.time()
 5         print(time.strftime('%Y-%m-%d %X'))
 6         x(*args,**kwargs)                       #被装饰函数的运行处
 7         stop_time = time.time()
 8         print("uesd time:%s" % (stop_time - start_time))
 9     return test    #######千万不能忘了return!!!!!!!!!
10 @aaa     #想装饰哪个函数,就放在哪个函数的前面
11 def test1():
12     time.sleep(2)
13     print("123123132")
14 @aaa
15 def test2(c):
16     time.sleep(3)
17     print("--->>",c)
18 test1()
19 test2("sd")
简单的装饰器
 1 log_list=[]
 2 log_1,log_2='xyz','abc'
 3 def log_in(log_in_1):     #设置选择的参数
 4     def login(func):        #被装饰函数
 5         def log(*args, **kwargs):    #被装饰函数内的参数
 6             if log_in_1 == "file":     #设置选项
 7                 with open("login.txt","r",encoding="utf-8") as log_file:
 8                     while True:
 9                         log_line=log_file.readline().strip('\n').split(',')
10                         if not log_line == [""]:
11                             log_list.append(log_line)
12                         else:
13                             break
14                 user_name = input("username1:").strip()
15                 pass_word = input("password1:").strip()
16                 count = 0
17                 for i in log_list:
18                     if user_name ==i[0]and pass_word==i[1]:
19                         print("welcome")
20                         func(*args, **kwargs)
21                         return 1
22                     else:
23                         if count == log_list.index(log_list[-1]):
24                             print("wrong")
25                         count +=1
26             elif log_in_1 == "neicun":     #设置选项
27                 user_name = input("username2:").strip()
28                 pass_word = input("password2:").strip()
29                 if user_name==log_1 and pass_word == log_2:
30                     print("welcome")
31                     func(*args, **kwargs)
32                     return 2
33                 else:
34                     print("wrong")
35 
36         return log      #######千万不能忘了return!!!!!!!!!
37     return login        #######千万不能忘了return!!!!!!!!!
38 @log_in(log_in_1='file')         #若调用时存在选择,则用最外层参数
39 def test1():
40     print("123")
41     return 1     #装饰器中必需要加一个返回值成功返回,此处才能返回
42                  #因为调用test的时候相当于调用上面的log,而log若无返回值,则test也无返回值,就会打印出none
43 @log_in(log_in_1='neicun')
44 def test2():
45     print("456")
46     return 2
47 
48 
49 test1()
50 test2()
复杂的装饰器

生成器:

定义:一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就会变成生成器 

作用:

这个yield的主要效果呢,就是可以使函数中断,并保存中断状态,中断后,代码可以继续往下执行,过一段时间还可以再重新调用这个函数,从上次yield的下一句开始执行。

另外,还可通过yield实现在单线程的情况下实现并发运算的效果

1 b=( i*2 for i in range(10))     #形成生成器,省内存
2 print(b)                        #若不调用,则不会存在于内存中,只有调用时才会现生成
3 
4 #b.__next__()  只有此方法可以一个一个 查看 生成器中的数据
5 
6 for i in range(5):     #若只调用前5个数,则只生成前5个在内存中,后面的都没生成
7     print(i)
生成器
1 def fib(x):           #用yield会把函数变成生成器
2     n=0               #只能用__next__()执行
3     a=0
4     b=1
5     while n <=x:
6         a,b=b,a+b                    #赋值语句,解释:
7         yield (a,b)   # 代替print     
8         n+=1                              
9     return 1                        
斐波那契

还可通过yield实现在单线程的情况下实现并发运算的效果

 1 import time
 2 baozi=["韭菜鸡蛋","青椒肉","牛肉","三鲜","猪肉白菜"]
 3 def eater(name):
 4     print("%s准备吃了"%name)
 5     while True:
 6 
 7         bao_zi=yield #待定的值
 8         print("1个%s包子被%s吃了"%(bao_zi,name))
 9 
10 def productor(name):
11     b=eater("邢韬")
12     b2 = eater("丽丽")
13     print("%s开始准备做包子啦"%name)
14     b.__next__()
15     b2.__next__()
16     for i in baozi:
17         time.sleep(1)
18         print("%s做好了2个%s馅包子,一人一个"%(name,i))
19         b.send(i)
20         b2.send(i)
21 
22 productor('厨师')
生成器并行

异常探测

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

2 、当__next__()超出生成器最大长度是,会出现异常

3 、当不知道生成器长度时,可使用抓住异常的方法去尝试

1 g = fib(6)
2 
3 while True:
4  try:                               #异常探测
5      x = next(g)                #不出错会无限循环
6      print('g:', x)
7  except StopIteration as e:     #出错执行这里
8      print('Generator return value:', e.value)
9      break
异常探测

迭代器

迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退。另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件

特点:

  1. 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
  2. 不能随机访问集合中的某个值 ,只能从头到尾依次访问
  3. 访问到一半时不能往回退
  4. 便于循环比较大的数据集合,节省内存

我们已经知道,可以直接作用于for循环的数据类型有以下几种:

一类是集合数据类型,如listtupledictsetstr等;

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

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

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

 

1 from collections import Iterator,Iterable   #调用模块
2 
3 Iterator([],Iterable)      
4 #判断是否为可迭代对象(可直接作用于FOR循环的对象如列表、元组等)
5 
6 isinstance((x for x in range(10)),Iterator) 
7 #判断是否为迭代器对象(可以被__next__()函数调用并不断返回下一个值的对象称为迭代器:Iterator)
8 
9 a=iter([1,2,3])   #把可迭代对象变为迭代器
迭代器

内置方法

1 all([-1,1,2,3])     #如果可迭代对象中所有元素都为真(非0即是真),则返回True
2 any([0,1])          #如果可迭代对象中任一元素为真(非0即是真),则返回True
3 ascii([88])         #变成字符串str格式
4 bin(8)              #十进制转2进制
5 bool(0)             #判断真假
内置方法1
 1 a=bytearray("abcde",encoding="utf-8")
 2 print(a[0])         #打印ascii码中的位置
 3 a[1]=110            #替换只能用ascii码替换
 4 print(a)
 5 ————————分割————————
 6 def test():pass
 7 
 8 callable(test)      #判断是否可调用(后面是否可以加括号)
 9 
10 ————————分割————————
11 
12 chr(80)             #返回ascii码对应的值,必须是数字
13 ord("p")            #返回在ascii码中的位置
14 exec()              #可执行字符串,可以算复杂的
15 ——————————分割————————
16 s=1
17 eval("s+1")      #运行字符串,只能算简单的
18 ——————————分割——————————
19 dir(b)              #查看可执行方法
内置方法2
 1 filter(lambda x:x>4,range(10))    #变成迭代器了,并只选择合格的值
 2 
 3 d = map(lambda x:x*x,range(10))     
 4 #也变成迭代器了,按方法输出所有的值,不考虑判断等等
 5 
 6 ——————————分割————————————
 7 e=frozenset([1,2,3,4,5,6,7])        #冻结集合,使其不可变
 8 
 9 globals()                           #整个文件所有变量变成键值的形式
10 locals()
11 
12 max(1,2,3)                               #返回最大值
13 
14 min(1,2,3)                               #返回最小值
15 
16 oct(16)                                  #8进制
17 
18 pow(2,8)                                 #幂,x的y次方
19 
20 round(1.22577,2)                         #对X四舍五入Y位
21 
22 range(0,20)[slice(2,5)]                  #切片  ==  range(0,20)[2:5]
内置方法3
 1 g={1:444,2:3231,3:213323,4:123213,5:223,6:31233}
 2 
 3 sorted(g.items())                        #根据键对字典进行排序
 4 
 5 sorted(g.items(),key=lambda x:x[1])      #把KEY变成值,就可以根据值来排序了
 6 
 7 ——————————分割——————————
 8 o=[1,2,3,4]
 9 p=["a","b","c","d"]                              
10 for i in zip(o,p):                  #一一对应   
11     print(i)
内置方法4

软件目录结构规范

Foo/    #项目名称

|-- bin/ #可执行文件目录

|   |-- foo #可执行文件     #启动时调用main.py主程序

|

|-- foo/ #主程序目录

 

|   |-- tests/ #测试

|   |   |-- __init__.py

|   |   |-- test_main.py

|   |

|   |-- __init__.py #包

|   |-- main.py #程序主入口

|

|-- docs/ #文档

|   |-- conf.py

|   |-- abc.rst

|

|-- setup.py #安装

|-- requirements.txt      #依赖关系

|-- README

 

详细参考 HTTP://WWW.blogs.com/alex3714/articles/5765046.HTML

 

简要解释一下:

1  bin/: 存放项目的一些可执行文件,当然你可以起名script/之类的也行。

2  foo/: 存放项目的所有源代码。

(1) 源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。

(2) 其子目录tests/存放单元测试代码;

(3) 程序的入口最好命名为main.py。

3  docs/: 存放一些文档。

4  setup.py: 安装、部署、打包的脚本。

5  requirements.txt: 存放软件依赖的外部Python包列表。

6  README: 项目说明文件。

除此之外,有一些方案给出了更加多的内容。比如LICENSE.txt,Archangel.txt文件等,我没有列在这里,因为这些东西主要是项目开源的时候需要用到。

 

关于README的内容

这个我觉得是每个项目都应该有的一个文件,目的是能简要描述该项目的信息,让读者快速了解这个项目。

它需要说明以下几个事项:

1  软件定位,软件的基本功能。

2  运行代码的方法: 安装环境、启动命令等。

3  简要的使用说明。

4  代码目录结构说明,更详细点可以说明软件的基本原理。

5  常见问题说明。

我觉得有以上几点是比较好的一个README。在软件开发初期,由于开发过程中以上内容可能不明确或者发生变化,并不是一定要在一开始就将所有信息都补全。但是在项目完结的时候,是需要撰写这样的一个文档的。

可以参考Re dis源码中read me的写法,这里面简洁但是清晰的描述了Re dis功能和源码结构。 

 

转载于:https://www.cnblogs.com/xt112233/p/9489497.html

你可能感兴趣的:(Python从零开始之Day4)