WEEK4:迭代器、装饰器、软件开发规范

  • 装饰器
     1 import time
     2 def timer(func): #timer(test1) func=test1
     3     def deco(*args,**kwargs):
     4         start_time=time.time()
     5         res=func(*args,**kwargs) #run test1()
     6         stop_time=time.time()
     7         print("the func run time is %s" %(stop_time-start_time))
     8         return res
     9     return deco
    10 @timer #test1=timer(test1)
    11 def test1():
    12     time.sleep(3)
    13     print("in the test1")
    14 
    15 # 向函数内传递参数须要在装饰器内部使用非固定参数*args和**kwargs
    16 @timer #test2=timer(test2)
    17 def test2(name):
    18     time.sleep(2)
    19     print("test2:",name)
    20 
    21 #获取函数的返回值,须要将func的运行结果赋值给变量res
    22 @timer
    23 def test3():
    24     return "this is test3 name"
    25 
    26 #调用
    27 test1()
    28 test2("ssss")
    29 print(test3())
    View Code
    • 定义:本质是函数,(装饰其余函数)就是为其余函数添加附加功能
    • 原则:
      • 不能修改被装饰的函数的源代码
      • 不能修改被装饰的函数的调用方式
         1 import time
         2 def timmer(func):
         3     def warpper(*args,**kwargs):
         4         start_time=time.time()
         5         func()
         6         stop_time=time.time()
         7         print("the func run time is %s" %(stop_time-start_time))
         8     return warpper
         9 @timmer
        10 def test1():
        11     time.sleep(3)
        12     print("in the test1")
        13 test1()
        View Code
    • 实现装饰器知识储备
      • 函数即“变量”
        • #补充知识:匿名函数
          calc=lambda x:x*3
          print(calc(3)) #结果为9
        • 定义一个函数,就至关于将函数体赋值给一个变量,这个变量的名称是函数名称
      • 高阶函数
        • 两个条件,知足其中之一即是高阶函数
          • 把一个函数名当作一个实参传递给另一个函数(在不修改被装饰函数源代码的状况下为其添加功能)
          • 返回值中包含函数名(不修改函数调用方式)
      • 嵌套函数
        在一个函数体内再用def定义函数
         1 x=0
         2 def grandpa():
         3     x=1
         4     def dad():
         5         x=2
         6         def son():
         7             x=3
         8             print(x)
         9         son()
        10     dad()
        11 grandpa()
        View Code
  • 生成器
      • 列表生成式 [ i*2 for i in range(10) ]或者 [ func(i) for i in range(10) ]  #占用很大的内存空间
      • 列表生成器c=( func(i) for i in range(10) ) #访问数据时才会生成,不然不存在,因此不占用内存,
    不支持切片
    #生成器只有在调用时才会生成相应的数据
      • 生成器获取下一个数据的方法c.__next__()
      • 生成器为何没法获取上一个数据?生成器之因此省内存,缘由就是只记住当前的数据(只记录当前的位置),没法获取以前的数据,只能获取下一个数据(只有一个__next__()方法)
    • 将斐波那契数列作成生成器
       1 def fib(max):
       2     n,a,b=0,0,1
       3     while n<max:
       4         yield b #转换成生成式
       5         a,b=b,a+b
       6         n+=1
       7     return "--done--"
       8 g=fib(100)
       9 while True:
      10     try:
      11         n=g.__next__() #获取下一个数值
      12         print(n)
      13     except StopIteration as e: #超出范围处理
      14         print("Generator return value:",e.value)
      15         break
      View Code
    • 生成器的并行运算
       1 import time
       2 def consumer(name): #消费者
       3     print("%s 准备吃包子啦!"%name)
       4     while True:
       5         baozi=yield
       6         print("包子[%s]来了,被[%s]吃了!"%(baozi,name))
       7 def producer(name):
       8     c=consumer("A")
       9     c2=consumer("B")
      10     c.__next__()
      11     c2.__next__()
      12     print("老子开始准备作包子了")
      13     for i in range(10):
      14         time.sleep(1)
      15         print("作了两个包子")
      16         c.send(i)
      17         c2.send(i)
      18 #协程
      19 producer("alex")
      20 
      21 # c=consumer("ChenRonghua")
      22 # c.__next__()
      23 # b1="韭菜馅"
      24 # c.send(b1) #send给yield传值
      25 # #next只唤醒生成器可是不传值,send唤醒后传值
      View Code
  • 迭代器
    能够直接做用于for循环的数据类型有如下几种:一、集合数据类型,如list、tuple、dict、set、str等,二、generator,包括生成器和带yield的generator function,这些直接做用于for循环的对象统称为可迭代对象:Iterable
    可使用isinstance()判断一个对象是不是Iterable对象:
    from collections import Iterable
    isinstance((x for x in range(10)),Iterator) #True
    isinstance([],Iterator) #False,[]、{}、'abc'均为False
    生成器都是迭代器对象,可是list、dict、str虽然都是可迭代的,却不是迭代器,把list、dict、str等可迭代的数据类型变成迭代器,可使用iter()函数,例如iter([])或者iter('abc')

    • 小结
      凡是可做用于for循环的对象都是可迭代类型,
      凡是可做用于next()函数的对象都是迭代器类型,他们表示惰性计算的序列
      集合数据类型如list、dict、str等都是可迭代的,但不是迭代器,不过能够经过iter()函数获取一个迭代器对象
      python的for循环本质上就是不断调用next()函数实现的
  • 内置函数
    • abs() #取绝对值
    • all() #可迭代对象中所有数据为真则返回true,不然为false,
    • any() #可迭代对象中有一个数据为真则为true,不然为false,空也为false
    • ascii() #将处理对象变成一个字符串(可打印的对象)
    • bin() #十进制数字转成二进制
    • oct() #十进制数字转成八进制
    • bool() #判断数据的真假
    • bytearray() #可修改的二进制字节格式
    • callable() #判断对象是否能够调用
    • chr() #将数字变成ascii表中的字符
    • ord() #将ascii表中的字符变成数字
    • compile() #将字符串变成可以执行的代码
      例如:code是一段函数直接变成的代码
      py_obj=compile(code,"err.log","exec")
      exec(py_obj)
      或者直接用exec(code)执行,不须要compile
    • dir() #查看对象的方法函数
    • divmod() #相除以后返回余数
    • eval() #将字符串变成字典
    • filter() #过滤出数据中本身想要的数据
    • map() #对传入的每个值按照前面的函数处理
    • functools.reduce() #将这次处理结果递交给下一次做为输入
    • frozenset() #冻结集合,将集合变为没法修改的集合
    • round() ##保留n位小数
    • sorted() #排序
    • zip() #将两个列表按照元素位置拼接在一块儿
  • json序列化和反序列化
    • 序列化
      import json
      info={
          "name":"alex",
          "age":22
      }
      f=open("test.txt","w")
      f.write(json.dumps(info))
      f.close()
    • 反序列化
      import json
      f=open("test.txt","r")
      data=json.loads(f.read())
      print(data["age"])
  • pickle序列化和反序列化
    • 序列化
      import pickle
      info={
          "name":"alex",
          "age":22
      }
      f=open("test.txt","wb")
      f.write(pickle.dumps(info)) #或者pickle.dump(info,f)
      f.close()
    • 反序列化
      import pickle
      f=open("test.txt","rb")
      data=pickle.loads(f.read()) #或者data=pickle.load(f)
      print(data["age"])
  • 软件目录结构规范
    • 目录结构以下图

      • 简要解释
        • bin/:存放项目的一些可执行文件,固然你能够起名script/之类的也行
        • foo/:存放项目的全部源代码
          • 源代码中全部的模块、包都应该放在此目录。不要置于顶层目录
          • 子目录test/存放单元测试代码
          • 程序的入口最好命名为main.py
        • docs/:存放一些文档
        • conf/:存放软件运行所需的配置文件
        • setup.py:安装、部署、打包的脚本
        • requirements.txt:存放软件依赖的外部python包列表
          • 方便开发者维护软件包依赖。开发过程当中新增的包添加进这个列表中,避免在setup.py安装依赖时漏掉软件包
          • 方便读者明确项目使用了哪些python包
        • README:项目说明文件
          • 软件定位,软件的基本功能
          • 运行代码的方法:安装环境、启动命令等
          • 简要的使用说明
          • 代码目录结构说明,更详细点能够说明软件的基本原理
          • 常见问题说明
    • 跨目录调用
      • __file__:当前文件的相对路径
      • 将当前工程目录添加到环境变量
        import sys,os
        BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        sys.path.append(BASE_DIR)
      • 调用from conf import settingsfrom core import main   #from后面跟子文件夹名字,import后面跟子文件夹下面的.py文件的名字
相关文章
相关标签/搜索