• Day4


    Day4 - Python基础4 迭代器、装饰器、软件开发规范

    1.迭代器&生成器

     生成器

     背景:通过列表生成式能生成一个列表,但受内存限制,列表的容量肯定是有限的。而且当列表元素很多时,会占用大量内存空间,如果只是使用其中的一些元素,那其它元素会造成空间浪费

     定义:基于以上原因,如果能通过算法推导出列表的元素,这样就不需要创建完整的list,可以节省空间。这种一边循环一边计算的机制,就叫生成器。

       格式:只需把列表生成式[]改成()即可

       方法:使用next()可以获取下一个元素,不过一般用for循环打印

     函数生成器:在函数中加入yield,函数就变成了一个生成器;而且还可以利用此特性,实现协程的效果

      

     1 #普通列表
     2 list_normal = [0,1,2,3,4,5,6,7,8,9,10]  #手动生成列表
     3 print(list_normal)
     4 #列表生成式
     5 list_auto = [i for i in range(11)]  #利用算法生成列表
     6 print(list_auto)
     7 
     8 #生成器
     9 list_generator = (i for i in range(11)) #把生成式[]改成()就是生成器了
    10 print(list_generator)
    11 #生成器方法
    12 print(next(list_generator))
    13 print(next(list_generator))
    14 for i in list_generator:
    15     print(i)
     1 #函数生成器
     2 def num_generator(num):
     3     i = 0
     4     while i <num:
     5         #print(i)
     6         yield i
     7         i +=1
     8     return 'done'
     9 
    10 nums = num_generator(5)
    11 print(nums)
    12 print(nums.__next__())
    13 print(nums.__next__())
    14 print("干点其它事")
    15 print(nums.__next__())
    16 print(nums.__next__())
    17 print(nums.__next__())
    18 #函数生成器异常捕获处理
    19 while True:
    20     try:
    21         print("nums:",next(nums))
    22     except StopIteration as e:
    23         print("nums gererator return value:",e.value)
    24         break
    函数生成器
     1 #单线程实现并发运算
     2 import time,os
     3 
     4 def command():
     5     print("开始ping啦")
     6     while True:
     7         addr = yield
     8         os.system("ping "+' '+ addr)
     9 
    10 def ips():
    11     t = command()
    12     t.__next__()
    13     print("开始分配IP地址")
    14     for i in range(2):
    15         if i == 0:
    16             continue
    17         else:
    18             address = "10.172.116.%s"%i
    19             time.sleep(1)
    20             t.send(address)
    21 ips()
    单线程实现并发运算  

     迭代器

      可迭代对象Iterable:

      可以被for循环的数据类型,包含二类:

      1.集合数据类型:list、dict、tuple、set、str等

      2.generator,包含生成器、带yield的generator function  

    1 from collections import Iterable
    2 from collections import Iterator
    3 
    4 #判断是否是可迭代对象
    5 isinstance([],Iterable)
    6 isinstance({},Iterable)
    7 isinstance((),Iterable)
    8 isinstance('string',Iterable)
    9 isinstance(100,Iterable)    #数字不可迭代

     迭代器Iterator:

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

      特性:

        把Iterable变成Iterator可以使用Iter()函数

        生成器都是Iterator对象,但list、tuple、dict等虽是Iterable,却不是Iterator

     1 #判断是否是迭代器
     2 isinstance([],Iterator)
     3 isinstance({},Iterator)
     4 isinstance((),Iterator)
     5 isinstance('string',Iterator)
     6 isinstance(100,Iterator)
     7 isinstance((x for x in range(10)),Iterator)
     8 
     9 #迭代对象转换成迭代器方法
    10 Iter_list = iter([1,2,3])
    11 print(iter_list)

     区别:

          Iterator对象表示的是一个数据流,可以被next()函数调用并不断返回下一个数据,直到数据抛出StopIteration错误。可以把Iterator看成是一个有序序列,但我们却不能提前知道序列长度,它可以表示一个无限大的数据流,如自然数,而这是list办不到的。 

     for循环本质上是通过不断调用next()实现的

     1 #for循环
     2 for i in [1,2,3]:
     3     print(i)
     4 
     5 #等同于下面的迭代器
     6 a = iter([1,2,3])
     7 while True:
     8     try:
     9         next(a)
    10     except StopIteration:
    11         break
    View Code

    2.装饰器

      python装饰器:http://blog.51cto.com/egon09/1836763

      定义:本质是函数,功能是装饰其它函数,就是为其它函数添加附加功能

      原则:1.不能修改被装饰的函数的源代码(对被装饰函数是透明的)

         2.不能修改被装饰的函数的调用方式

     实现装饰器知识储备:(高阶函数+嵌套函数=装饰器)

        1.函数即“变量”

         

        2.高阶函数

         a.把一个函数名当做实参传给另一个函数(在不修改被装饰函数源代码的情况下为其添加功能)

         b.返回值中包含函数名(不修改函数的调用方式)

     1 #高阶函数
     2 def bar():
     3      time.sleep(3)
     4      print('in the bar')
     5 
     6 def test2(func):
     7     print(func)
     8     return func
     9 
    10 t = test2(bar)
    11 t() #run bar
    12 
    13 bar=test2(bar)  #把之前函数bar名称覆盖了
    14 bar()
    高阶函数

        3.嵌套函数

         定义:一个函数体内用def去声明一个新的函数

    1 #嵌套函数
    2 def foo():
    3     print('in the foo')
    4     def bar():
    5         print('in the bar')
    6     bar()
    7 foo()
    嵌套函数
     1 #局部作用域和全局作用域的访问顺序
     2 x=0
     3 def grandpa():
     4     x=1
     5     def dad():
     6         x=2
     7         def son():
     8             x=3
     9             print(x)
    10         son()
    11     dad()
    12 grandpa()   #结果是3,从最里面找变量
    局部作用域和全局作用域的访问顺序

        4.装饰器案例

     1 #装饰器案例1
     2 #运行test1-->等同于运行deco-->运行deco过程中会运行原来的test1函数-->并附加了计时功能
     3 def timer(func):    #嵌套函数 timer(test1) func=test1
     4     def deco():     #高阶函数
     5         start_time = time.time()
     6         func()      #run test1
     7         stop_time = time.time()
     8         print("run time :%s"%(stop_time-start_time))
     9     return deco     #返回deco的内存地址
    10 
    11 @timer  #等同于test1 = timer(test1)
    12 def test1():
    13     time.sleep(3)
    14     print('in the test1')
    15 
    16 test1() #run deco
    装饰器案例1
     1  1 #装饰器案例2
     2  2 #实现不定量传参,装饰器更有扩展性
     3  3 def timer(func):    #嵌套函数 timer(test1) func=test1
     4  4     def deco(*arg,**kwargs):     #高阶函数
     5  5         start_time = time.time()
     6  6         func(*arg,**kwargs)      #run test1
     7  7         stop_time = time.time()
     8  8         print("run time :%s"%(stop_time-start_time))
     9  9     return deco     #返回deco的内存地址
    10 10 
    11 11 @timer  #等同于test1 = timer(test1)
    12 12 def test1():
    13 13     time.sleep(3)
    14 14     print('in the test1')
    15 15 
    16 16 @timer  #等同于test2 = timer(test2)=deco test2(name)=deco(name)
    17 17 def test2(name):
    18 18     print('test2:',name)
    19 19 
    20 20 test1() #run deco
    21 21 test2('sam')
    装饰器案例2-传参
     1 #网站认证装饰器-初版
     2 #需求:登录index页面不需要认证,登录home/bbs要认证(使用装饰器)
     3 user,passwd = 'sam','123'
     4 def auth(func):    #装饰器
     5     def wrapper():
     6         username = input("Username:").strip()
     7         password = input("Password:").strip()
     8         if username == user and password == passwd:
     9             print("登录成功!")
    10             func()
    11         else:
    12             print("用户名或密码错误.")
    13     return wrapper
    14 
    15 def index():    #不认证
    16     print("Welcome to the index page.")
    17 
    18 @auth
    19 def home():    #装饰器认证
    20     print("Welcome to the home page.")
    21 
    22 @auth
    23 def bbs():     #装饰器认证
    24     print("Welcome to the bbs page.")
    25 
    26 home()
    27 bbs()
    网站认证装饰器-初版
     1 #网站认证装饰器-进阶版
     2 #需求:登录index页面不需要认证,登录home/bbs要使用认证方式(使用装饰器),home传参数且有返回值
     3 user,passwd = 'sam','123'
     4 def auth(func):
     5     def wrapper(*args,**kwargs):
     6         username = input("Username:").strip()
     7         password = input("Password:").strip()
     8         if username == user and password == passwd:
     9             print("登录成功!")
    10             res = func(*args,**kwargs)
    11             #print("---认证之后---")
    12             return res
    13         else:
    14             print("用户名或密码错误.")
    15     return wrapper
    16 
    17 def index():
    18     print("Welcome to the index page.")
    19 
    20 @auth
    21 def home(*args):
    22     print("Welcome to the home page.",args)
    23     return "From home page"
    24 
    25 @auth
    26 def bbs():
    27     print("Welcome to the bbs page.")
    28 
    29 #home()
    30 print(home('sam'))
    网站认证装饰器-进阶版
     1 #网站认证装饰器-终极版
     2 #需求:登录index页面不需要认证,登录home/bbs要使用不同的认证方式local/ldap(使用装饰器),home传参数且有返回值
     3 user,passwd = 'sam','123'
     4 def auth(auth_type):
     5     #print("auth func:",auth_type)
     6     def outer_wrapper(func):
     7         def wrapper(*args,**kwargs):
     8             #print("wrapper func args:", *args, **kwargs)
     9             if auth_type == 'local':
    10                 username = input("Username:").strip()
    11                 password = input("Password:").strip()
    12                 if username == user and password == passwd:
    13                     print("登录成功!")
    14                     res = func(*args,**kwargs)
    15                     #print("---认证之后---")
    16                     return res
    17                 else:
    18                     print("用户名或密码错误.")
    19             elif auth_type == 'ldap':
    20                 print("使用Ldap认证")
    21         return wrapper
    22     return outer_wrapper
    23 
    24 def index():
    25     print("Welcome to the index page.")
    26 
    27 @auth(auth_type='local')    #home=auth
    28 def home(*args):
    29     print("Welcome to the home page.",args)
    30     return "From home page"
    31 
    32 @auth(auth_type='ldap')
    33 def bbs():
    34     print("Welcome to the bbs page.")
    35 
    36 home()
    37 bbs()
    网站认证装饰器-终极版

    3.Json & pickle 数据序列化

     xml逐渐被json取代

     Json不支持函数序列化,只能处理简单的数据类型

    #序列化
    import json
    
    def sayhi(name):
        print("hello,",name)
    
    info = {
        'name':'alex',
        'age':22,
        #'func':sayhi    #不能序列化函数
    }
    
    f = open("test.text","w")
    f.write( json.dumps( info) )
    
    info['age'] = 21
    f.write( json.dumps( info) )
    
    f.close()
    
    #反序列化
    import json
    
    f = open("test.text","r")
    
    #data = json.loads(f.read()) #data = pickle.loads(f.read())
    
    for line in f:
        print(json.loads(line))
    Json

     Json是不同开发语言都支持的交互方式,pickle是python自有的

     pickle可以序列化所有数据类型,但函数不能序列

     1 #序列化
     2 import pickle
     3 
     4 def sayhi(name):
     5     print("hello,",name)
     6 
     7 info = {
     8     'name':'alex',
     9     'age':22,
    10     'func':sayhi
    11 }
    12 
    13 
    14 f = open("test.text","wb")
    15 
    16 pickle.dump(info,f) #和f.write( pickle.dumps( info) )功能一样
    17 
    18 f.close()
    19 
    20 #反序列化
    21 def sayhi(name):
    22     print("hello2,",name)
    23 
    24 f = open("test.text","rb")
    25 
    26 data = pickle.load(f) #和data = pickle.loads(f.read())功能一样
    27 
    28 print(data["func"]("Alex"))
    View Code

     注:dump一次load一次,不要dump多次

    4.软件目录结构规范

     假设项目名为Foo

    Foo/
    |-- bin/
    |   |-- foo
    |
    |-- foo/
    |   |-- tests/
    |   |   |-- __init__.py
    |   |   |-- test_main.py
    |   |
    |   |-- __init__.py
    |   |-- main.py
    |
    |-- docs/
    |   |-- conf.py
    |   |-- abc.rst
    |
    |-- setup.py
    |-- requirements.txt
    |-- README
    

    简要解释一下:

    1. bin/: 存放项目的一些可执行文件,当然你可以起名script/之类的也行。
    2. foo/: 存放项目的所有源代码。(1) 源代码中的所有模块、包都应该放在此目录。不要置于顶层目录。(2) 其子目录tests/存放单元测试代码; (3) 程序的入口最好命名为main.py
    3. docs/: 存放一些文档。
    4. setup.py: 安装、部署、打包的脚本。
    5. requirements.txt: 存放软件依赖的外部Python包列表。
    6. README: 项目说明文件。
  • 相关阅读:
    软件工程——第一次作业
    软件工程结对编程第二次作业
    软件工程结对编程第一次作业
    软件工程第三次作业
    软件工程第二次作业
    软件工程第一次作业
    阿里云服务器ECS WindowsServer2016配置IIS遇到的坑
    微信小程序跳坑指南——小程序上线半年后遇到的坑总结
    VS2013 RC 此模板尝试加载组件程序集 “NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral.........
    Mysql主从复制原理及配置
  • 原文地址:https://www.cnblogs.com/pynetwork/p/8980509.html
Copyright © 2020-2023  润新知