zoukankan      html  css  js  c++  java
  • 函数递归,匿名、内置行数,模块和包,开发规范

    一、递归与二分法

      一、递归

      1、递归调用的定义

      递归调用:在调用一个函数的过程中,直接或间接地调用了函数本身 

      2、递归分为两类:直接与间接

    #直接
    def func():
        print('from func')
        func()
    
    func()
    # 间接
    def foo():
        print('from foo')
        bar()
    
    def bar():
        print('from bar')
        foo()
    
    foo()

      3、递归调用的特点和使用的注意点

    递归调用:在调用一个函数的过程中,直接或间接地调用了函数本身
    python中的递归效率低,需要在进入下一次递归时保留当前的状态
    在其他语言中可以有解决方法:尾递归优化,即在函数的最后一步(而非最后一行)调用自己,尾递归优化:http://egon09.blog.51cto.com/9161406/1842475;但是python又没有尾递归,且对递归层级做了限制
    
    #总结递归的使用:
    1. 必须有一个明确的结束条件
    2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
    3. 递归效率不高,递归层次过多会导致栈溢出
    在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出

      4、递归的执行分为两个阶段:递推(询问的过程)和回溯(回答的过程)

     1 #获知age(5)的值
     2 # age(5)=age(4)+2
     3 # age(4)=age(3)+2
     4 # age(3)=age(2)+2
     5 # age(2)=age(1)+2
     6 # age(1)=18
     7 #
     8 # age(n)=age(n-1)+2 #n>1
     9 # age(1)=18 #n=1
    10 
    11 def age(n):
    12     if n == 1:
    13         return 18
    14     return age(n-1)+2
    15 
    16 print(age(5))

      5、可以递归的最大深度

     1 #虽然可以设置,但是因为不是尾递归,仍然要保存栈,内存大小一定,不可能无限递归
     2 import sys
     3 sys.getrecursionlimit()  ##获取目前默认递归的最大深度,默认深度是1000
     4 sys.setrecursionlimit(500)  ##更改默认递归的最大深度
     5 n=1
     6 def test():
     7     global n
     8     print(n)
     9     n+=1
    10     test()
    11 test()

      6、应用场景:有许多层的列表,要取出所有元素——设置结束条件使用递归

    l =[1, 2,'list' ,[3, [4, 5, 6, [7, 8, [9, 10, [11, 12, 13, [14, 15,[16,[17,]],19]]]]]]]
    def search(l):
        for item in l:
            # if type(item) is list:
            if isinstance(item,list): ##判断数据类型是否是列表
                search(item)
            else:
                print(item)
    
    search(l)

      二、二分法

      1、二分法的产生

    一个按照从小到大排列的数字列表中找到指定的数字,遍历的效率太低,用二分法(算法的一种,算法是解决问题的方法)可以极大低缩小问题规模

      2、 二分法的作用:不断将列表切分成两份,减小压力

     1 l = [1,2,5,6,77,1001,1165,2340]
     2 def search(l,num):
     3     print(l)
     4     if len(l) > 1:
     5         mid_index = len(l) // 2 #相除取整
     6         if num > l[mid_index]:
     7             #in the right
     8             l = l[mid_index+1:]
     9         elif num < l[mid_index]:
    10             #in the left
    11             l = l[:mid_index]
    12         else:
    13             print('find it')
    14             return
    15     else:
    16         if l[0] == num:
    17             print('find it')
    18         else:
    19             print('not exists')
    20         return
    21     search(l,num) #重复的可以放在if里面
    22 search(l,77)

    二、匿名函数

      一、什么是匿名函数

    # 有名函数
    def f1(m):
    print(f1(3))
    # 匿名函数
    lambda n:n*2

       二、匿名函数的应用场景

    匿名函数自带return,只能使用一次
    #匿名函数即没有绑定名字的函数,意味着只能使用一次就会回收
    应用场景:只使用一次的功能

      三、匿名函数的使用

    salaries={
        'egon':3000,
        'alex':10000000,
        'wupeiqi':10000,
        'yuanhao':2000
    }
    
    def f1(k):
        return salaries[k]

      1、max、min与 lambda结合

    print(max(salaries,key=lambda k:salaries[k]))
    print(min(salaries,key=lambda k:salaries[k]))

      2、sorted与lambda结合

    print(sorted(salaries,key=lambda k:salaries[k]))
    print(sorted(salaries,key=lambda k:salaries[k],reverse=True))

      3、map(映射)与lambda结合

      将原来的元素进行处理后,重新赋值给原变量

    l=['alex','egon','wzs','yuanhao']
    print(list(map(lambda x:x+'123',l)))

      4、reduce(合并)与lambda结合

      计算0到100数字的和

    1 from functools import reduce
    2 # reduce(lambda 表达式,计算范围,计算的初始值)
    3 res=reduce(lambda x,y:x+y,range(1,100),100)
    4 print(res)

      5、filter(过滤)与lambda结合

      过滤出列表中以123结尾的元素

    l=['alex123','egon123','wzs123','yuanhao']
    print(list(filter(lambda name:name.endswith('123'),l)))

      6、扩展: 拉链函数

    l1=[1,2,3]
    s1='hello'
    res = zip(l1,s1)
    print(list(res))
    
    res=zip(salaries.values(),salaries.keys())
    print(max(res)[1])
    1 t1=(111,'a')
    2 t2=(11,'b',123,'c')
    3 print(t1 < t2)
    元素比较大小:从左到右比较元素的大小

    三、内置函数

      一、什么是内置函数

    内置函数:python将简单的功能内置到语言中,使用者不用定义,可以直接使用
    内置函数链接:https://docs.python.org/3/library/functions.html?highlight=built#ascii

      二、常用的内置函数

      

      友情链接:http://www.cnblogs.com/xiao1/p/5856890.html

      1、优先掌握的函数

    max min sorted map filter sum bool chr divmod enumerate 
    id input print isinstance iter len open pow type zip
    from _functools import reduce

      2、数学运算

    abs(-5)                          # 取绝对值,也就是5
    round(2.6)                       # 四舍五入取整,也就是3.0
    pow(2, 3)                        # 相当于2**3,如果是pow(2, 3, 5),相当于2**3 % 5
    cmp(2.3, 3.2)                    # 比较两个数的大小
    divmod(9,2)                      # 返回除法结果和余数,分页显示内容,计算页数
    max([1,5,2,9]) # 求最大值 min([9,2,-4,2]) # 求最小值 sum([2,-1,9,12]) # 求和

      3、类型转换

    int("5")                         # 转换为整数 integer
    float(2)                         # 转换为浮点数 float
    long("23")                       # 转换为长整数 long integer
    str(2.3)                         # 转换为字符串 string
    complex(3, 9)                    # 返回复数 3 + 9i
    bytes()                          # 字节
    list((1,2,3))                    # 转换为表 list
    tuple([2,3,4])                   # 转换为定值表 tuple
    dict(a=1,b="hello",c=[1,2,3])    # 构建词典 dictionary
    set()                            # 转换成集合
    slice(5,2,-1)                    # 切片操作
     1 # bytes object
     2 b = b"example"
     3 # str object
     4 s = "example"
     5 # str to bytes
     6 sb = bytes(s, encoding = "utf8")
     7 print(type(sb))
     8 # bytes to str
     9 bs = str(b, encoding = "utf8")
    10 # an alternative(可替代的方法) method
    11 # str to bytes
    12 sb2 = str.encode(s)
    13 # bytes to str
    14 bs2 = bytes.decode(b)
    python str与bytes之间的转换

      ASCII表中的字符和序号之间互相转好,应用场景:生成随机验证码

    #65-90是大写A-Z
    print(chr(65))
    print(chr(90))
    #97-122是小写a-z
    print(chr(97))
    print(chr(122))
    print(ord('A'))
    #48-57是数字0-9
    print(chr(48))
    print(chr(57))

       bool()布尔判断,在python中,为False的情况:空(字符 ‘’,列表 [],元组 (),字典 {}),0,0.0,None

    bool(0)                          # 转换为相应的真假值,在Python中,0相当于False

      进制显示

    bin(56)                          # 返回一个字符串,表示56的二进制数
    hex(56)                          # 返回一个字符串,表示56的十六进制数
    oct(56)                          # 返回一个字符串,表示56的八进制数

      判断元素是否为True

    all([True, 1, "hello!"])         # 是否所有的元素都相当于True值
    any(["", 0, False, [], None])    # 是否有任意一个元素相当于True值

      排序

    sorted([1,5,3])                  # 返回正序的序列,也就是[1,3,5]
    reversed([1,5,3])                # 返回反序的序列,也就是[3,5,1]

      4、类、对象、属性

    # define class
    class Me(object):
        def test(self):
            print "Hello!"
    def new_test():
        print "New Hello!"
    me = Me()
    object()
    hasattr(me, "test") # 检查me对象是否有test属性 getattr(me, "test") # 返回test属性 setattr(me, "test", new_test) # 将test属性设置为new_test delattr(me, "test") # 删除test属性 isinstance(1,int) # 检查对象是否是类的对象,返回True或False issubclass(Me, object) # Me类是否为object类的子类

      5、hash哈希值 :应用——数据校验

    hash(object)
    如果对象object为哈希表类型,返回对象object的哈希值。哈希值为整数,在字典查找中,哈希值用于快递比价字典的键。
    两个数值如果相等,则哈希值也相等。

      6、名称空间 局部名称vars()、locals(),全局名称空间global(),显示形式是字典

    print(vars() is locals())
    print(globals())

      7、__import__()  可以导入字符串,import不能导入字符串

    # import "time" #不能导入字符串
    # import time
    m=input('>>:')
    print(type(m))
    obj=__import__(m)  ##这样就可以导入字符串了
    obj.sleep(2)
    print(m)

      8、compile编译,执行exec、eval (了解)

        1、compile编译

      语法

    compile(str,filename,kind)
    filename:用于追踪str来自于哪个文件,如果不想追踪就可以不定义
    kind可以是:single代表一条语句,exec代表一组语句,eval代表一个表达式

      应用

    s="for i in range(10):print(i)"
    code=compile(s,'','exec')
    exec(code)  ##有返回结果
    
    s1="1+2+3"
    code1=compile(s1,'','eval')
    eval(code1) ##没有返回结果
        2、eval与exec

      eval 提取字符串内的表达式执行,并返回结果(可执行语句会报错)
      exec 执行字符串内的表达式或语句,没有返回结果

      语法

    eval(str,[,globals[,locals]])
    exec(str,[,globals[,locals]])

      举例

    1 s1="1+2+3"
    2 # s1="['a','b','c']"
    3 s2="for i in range(10):print (i)"
    4 print(eval(s1))
    5 print(exec(s1))
    6 print(exec(s2))

    四、模块

      一、模块介绍

      1、什么是模块

    一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。

      2、为何使用模块

    如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。
          随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用

      import加载的模块分为四个通用类别

    1、使用python编写的代码(.py文件)
    2、已被编译为共享库或DLL的C或C++扩展
    3、好一组模块的包
    4、使用C编写并链接到python解释器的内置模块

      3、导入模块都干了哪些事?

    1、执行源文件
    2、以一个源文件的全局名称空间
    3、在当前位置拿到一个模块名,指向2创建的名称空间

       4、python文件的两种用途

    .py文件的两种用途:1、当做脚本运行 2、当做模块被加载运行
    
    文件当做脚本运行时,__name__等于__main__
    文件当做模块被加载运行时,__name__等于模块名
    if __name__ == '__main__':
        # 当做脚本使用
        func1()
        func2()
        func3()
    # main  #回车会导入if __name__ == '__main__':

      二、使用import导入模块

      模块代码文件:spam.py

    #spam.py
    # print('from the spam.py')
    # 限制*的导入内容
    # _money=1000 #对*隐藏,即*无法调用(from spam import *)
    # __all__ = ['money','x'] # *只能调用赋予给__all__的名称 (from spam import *)
    money=10000000000000
    def read1():
        print('spam->read1->money',money)
    
    def read2():
        print('spam->read2 calling read')
        read1()
    
    def change():
        global money
        money=0

      1、导入模块并执行

      test.py

    import spam
    money=100
    spam.read1()
    spam.read2()
    spam.change()
    spam.read1()
    print(money)

      2、as取别名  

        用途:1、模块名非常长; 2、更改模块的功能

      测试文件

    1 def sqlparse():
    2     print('mysql sqlparse')
    mysql.py
    1 def sqlparse():
    2     print('oracle sqlparse')
    oracle.py

      导入模块,并执行

    1 import spam as s1
    2 money = 10000000
    3 spam.change()
    4 print(spam.money)
    模块名比较长
    1 sql_type = input('sql_type>>')
    2 if sql_type == 'mysql':
    3     import mysql as sql  ##引用不同的模块,因为实现的功能是相同的,所以可以起相同的别名
    4 elif sql_type == 'oracle':
    5     import oracle as sql
    6 sql.sqlparse()
    传入的内容调用不同的模块

      3、导入多个模块:模块之间用逗号隔开(不建议这么写,还是不同模块分行写为好)

    import os,sys,requests

      4、模块导入的特点

      模块只在第一次导入时才会执行,之后的导入都是直接引用内存已经存在的结果

     1 import spam
     2 import spam
     3 import spam
     4 import spam
     5 
     6 #验证是否已经在内存
     7 import sys
     8 # print(sys.modules) #存放的是已经加到内存的模块
     9 print('spam' in sys.modules)   #查看一个模块是否加到内存中
    10 import spam
    11 print('spam' in sys.modules)
    导入,并验证是否已在内存中 

      三、from....import...导入模块

      1、对比import导入模块,from....import...的优缺点

    1 对比import spam,会将源文件的名称空间'spam'带到当前名称空间中,使用时必须是spam.名字的方式
    2 而from 语句相当于import,也会创建新的名称空间,但是将spam中的名字直接导入到当前的名称空间中,在当前名称空间中,直接使用名字就可以了
    3 优点:使用源文件内的名字时,无需加前缀,使用方便
    4 缺点:容易与当前文件的名称空间内的名字混淆,会覆盖原来名字的值

      2、语法范例

    1 from spam import money,read1,read2
    2 money = 10
    3 print(money)
    4 # g=read1()
    5 g=read2()
    6 print(g)

      3、将模块导入并起别名

    # # from spam import read1 as m
    from spam import money as m
    # print(m)

      4、*的使用  (不建议使用*)

    #要引用的源文件里面的内容很多时,可以使用*代替所有(更容易与当前文件的名称空间冲突),但是不建议使用
    
    _money=1000 #将调用的名字前面加_,*就无法调用该名字(在源文件修改)
    __all__ = ['money','x'] # *只能调用赋予给__all__的名称(在源文件修改)
    from spam import *

      四、模块的搜索路径

      1、模块查找的顺序

    查找顺序:内存---->>内置模块---->>硬盘

      范例

    import time
    import importlib
    import spam
    time.sleep(30)
    # import spam
    # print(spam.money)
    
    importlib.reload(spam)  ##重启加载spam,可以使用到测试环境
    print(spam.money)

      2、模块的注意事项

    注意:
        1、Python程序只有重新加载才能生效
        2、Python自带的模块名不能使用

      3、搜索路径和注意事项

    当一个命名为spam的模块被导入时
        解释器首先会从内建模块中寻找该名字
        找不到,则去sys.path中找该名字
    sys.path从以下位置初始化
        1 执行文件所在的当前目录
        2 PTYHONPATH(包含一系列目录名,与shell变量PATH语法一样)
        3 依赖安装时默认指定的
    注意:在支持软连接的文件系统中,执行脚本所在的目录是在软连接之后被计算的,换句话说,包含软连接的目录不会被添加到模块的搜索路径中
    在初始化后,我们也可以在python程序中修改sys.path,执行文件所在的路径默认是sys.path的第一个目录,在所有标准库路径的前面。这意味着,当前目录是优先于标准库目录的,需要强调的是:我们自定义的模块名不要跟python标准库的模块名重复

      4、添加到path环境变量

    import sys
    print(sys.path)
    # 添加path环境变量
    # 加到最后面
    sys.path.append(r'G:dataPyCharm_Projects19day5模块模块的搜索路径aaa')
    # 加到最前面
    sys.path.insert(0,r'G:dataPyCharm_Projects19day5模块模块的搜索路径aaa')
    
    import spam
    
    from aaa import #模块的搜索路径

      五、模块的重载

      考虑到性能的原因,每个模块只被导入一次,放入字典sys.module中,如果你改变了模块的内容,你必须重启程序,python不支持重新加载或卸载之前导入的模块

      有的同学可能会想到直接从sys.module中删除一个模块不就可以卸载了吗,注意了,你删了sys.module中的模块对象仍然可能被其他程序的组件所引用,因而不会被清楚。

      特别的对于我们引用了这个模块中的一个类,用这个类产生了很多对象,因而这些对象都有关于这个模块的引用。

      如果只是你想交互测试的一个模块,使用 importlib.reload(), e.g. import importlib; importlib.reload(modulename),这只能用于测试环境。

    1 def func1():
    2     print('func1')
    aa.py
    1 import time,importlib
    2 import aa
    3 
    4 time.sleep(20)
    5 # importlib.reload(aa)
    6 aa.func1()
    reload.py

    五、包

      http://www.cnblogs.com/linhaifeng/articles/6379069.html

       一、包的简介

      1、什么是包

    ##官网的解释
    包是一种通过使用‘.模块名’来组织Python模块名称空间的方式
    ##详细解释
    包就是一个含有__init__.py文件的文件夹,所以我们创建包的目的就是为了用文件/模块组织起来。
    1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法
    2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)
    3. import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
    ##强调:
      1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
      2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块
    包A和包B下有同名模块也不会冲突,如A.a与B.a来自俩个命名空间

      2、为何要使用包

    随着功能越写越多,我们无法将所有功能都放到一个文件中,于是我们使用模块去组织功能,而随着模块越来越多,我们需要用文件夹将模块文件组织起来,依次来提供程序的结构性和可维护性

      3、注意事项

    1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。
    2.对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
    3.对比import item 和from item import name的应用场景:
    如果我们想直接使用name那必须使用后者。

      4、上课流程

    实验一
        准备:
            执行文件为test.py,内容
            #test.py
            import aaa
            同级目录下创建目录aaa,然后自建空__init__.py(或者干脆建包)
    
        需求:验证导入包就是在导入包下的__init__.py
    
        解决:
            先执行看结果
            再在__init__.py添加打印信息后,重新执行
    
    2、实验二
        准备:基于上面的结果
    
        需求:
            aaa.x
            aaa.y
        解决:在__init__.py中定义名字x和y
    
    3、实验三
        准备:在aaa下建立m1.py和m2.py
            #m1.py
            def f1():
                print('from 1')
            #m2.py
            def f2():
                print('from 2')
        需求:
            aaa.m1 #进而aaa.m1.func1()
            aaa.m2 #进而aaa.m2.func2()
    
        解决:在__init__.py中定义名字m1和m2,先定义一个普通变量,再引出如何导入模块名,强调:环境变量是以执行文件为准
        
    
    4、实验四
        准备:在aaa下新建包bbb
    
        需求:
            aaa.bbb
    
        解决:在aaa的__init__.py内导入名字bbb
    
    5、实验五
        准备:
            在bbb下建立模块m3.py
            #m3.py
            def f3():
                print('from 3')
        需求:
            aaa.bbb.m3 #进而aaa.bbb.m3.f3()
    
        解决:是bbb下的名字m3,因而要在bbb的__init__.py文件中导入名字m3,from aaa.bbb import m3
    
    6、实验六
        准备:基于上面的结果
    
        需求:
            aaa.m1()
            aaa.m2()
            aaa.m3()
            进而实现
            aaa.f1()
            aaa.f2()
            aaa.f3()
            先用绝对导入,再用相对导入
            
        解决:在aaa的__init__.py中拿到名字m1、m2、m3
        包内模块直接的相对导入,强调包的本质:包内的模块是用来被导入的,而不是被执行的
        用户无法区分模块是文件还是一个包,我们定义包是为了方便开发者维护
    
    7、实验七
        将包整理当做一个模块,移动到别的目录下,操作sys.path
    View Code

      二、包的使用

      1、测试文件:执行文件与测试文件在同级目录下

    包
    ├── aaa
    │   ├── bbb
    │   │   ├── __init__.py
    │   │   ├── m3.py
    │   │   └── __pycache__
    │   ├── __init__.py
    │   ├── m1.py
    │   ├── m2.py
    │   └── __pycache__
    └── run.py
    ##文件内容
    
    #m1.py
    def func1():
        print('f1')
    
    #m2.py
    def func2():
        print('f2')
    
    #m3.py
    def func3():
        print('f3')
    文件内容

      2、包的使用之import

      单独导入包名称时,不会导入包中的所有包含的所有子模块

    #在与aaa同级的run.py
    import aaa
    aaa.m1.func1()
    
    
    执行结果会出现如下错误:
    ModuleNotFoundError: No module named 'm1'

      解决方法

    #与aaa底下的__init__.py
    from .m1 import func1
    
    #导入模块,执行aaa同级的run.py的结果
    import aaa
    
    f1

      需要注意的:

      from后import导入的模块,必须是明确的一个不能带点,否则会有语法错误,如:from a import b.c是错误语法

        from aaa.bbb.m3 import func3

       3、from aaa.bbb.m3 import * :从一个包中导入所有*

     想从包api中导入所有,实际上该语句只会导入包api下__init__.py文件中定义的名字,我们可以在这个文件中定义__all___:

    #在__init__.py中定义
    x=10
    
    def func():
        print('from api.__init.py')
    
    __all__=['x','func','policy']

      4、绝对导入和相对导入

      最顶级包是aaa是给用户使用的,然后在aaa内部也会有彼此之间相互导入的需求,这时就有绝对和相对导入两种方式。

      绝对导入:以aaa作为起始

      相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)

          

       例:想在aaa/bbb/func3.py中导入aaa/ccc/func4.py
    
        绝对导入
            在func3.py上写入下面的代码
    from aaa.ccc.m4 import func4
            与run.py同级的__init__.pyd导入相应的模块
    from aaa.bbb.m3 import func4
            在run.py上的写入下面的代码直接调用
    aaa.func4()
    
        
        相对导入
            在func4.py上写入下面的代码
    from ..ccc.m4 import func4
            与run.py同级的__init__.pyd导入相应的模块
    from aaa.bbb.m3 import func4
            在run.py上的写入下面的代码直接调用
    aaa.func4()

      5、包以及包所包含的模块都是用来被导入的,而不是被直接执行的。而环境变量都是以执行文件为准的

      添加环境变量

    import sys
    sys.path.append(r'C:UsersCTB-BJB-0012PycharmProjectspython36s19day5包xxxyyy')
    import aaa
    1 from .m1 import func1
    2 from .m2 import func2
    3 from .bbb.m3 import func3
    4 from .bbb.m3 import func4
    aaa同级的__init__.py内容
    1 from ..ccc.m4 import func4
    2 def func3():
    3     print('f3')
    4     func4()
    m3.py文件内容
    1 import sys
    2 sys.path.append(r'C:UsersCTB-BJB-0012PycharmProjectspython36s19day5包xxxyyy')
    3 import aaa
    4 aaa.func1()
    5 aaa.func2()
    6 aaa.func3()
    运行run.py文件内容

      运行文件使用import直接导入所需模块的功能(使用了解目录结构):

        导入:import aaa.ccc.m4 

        调用:aaa.ccc.c4.func4()

      6、包的分发(了解)

      学习链接网址:https://packaging.python.org/tutorials/distributing-packages/

    六、软件开发规范

      一、软件目录规范如下

      

      二、常用模块的使用

      1 #=============>bin目录:存放执行脚本
      2 #start.py
      3 import sys,os
      4 
      5 BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
      6 sys.path.append(BASE_DIR)
      7 
      8 from core import core
      9 from conf import my_log_settings
     10 
     11 if __name__ == '__main__':
     12     my_log_settings.load_my_logging_cfg()
     13     core.run()
     14 
     15 #=============>conf目录:存放配置文件
     16 #config.ini
     17 [DEFAULT]
     18 user_timeout = 1000
     19 
     20 [egon]
     21 password = 123
     22 money = 10000000
     23 
     24 [alex]
     25 password = alex3714
     26 money=10000000000
     27 
     28 [yuanhao]
     29 password = ysb123
     30 money=10
     31 
     32 #settings.py
     33 import os
     34 config_path=r'%s\%s' %(os.path.dirname(os.path.abspath(__file__)),'config.ini')
     35 user_timeout=10
     36 user_db_path=r'%s\%s' %(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
     37                      'db')
     38 
     39 
     40 #my_log_settings.py
     41 """
     42 logging配置
     43 """
     44 
     45 import os
     46 import logging.config
     47 
     48 # 定义三种日志输出格式 开始
     49 
     50 standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' 
     51                   '[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字
     52 
     53 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
     54 
     55 id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
     56 
     57 # 定义日志输出格式 结束
     58 
     59 logfile_dir = r'%slog' %os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  # log文件的目录
     60 
     61 logfile_name = 'all2.log'  # log文件名
     62 
     63 # 如果不存在定义的日志目录就创建一个
     64 if not os.path.isdir(logfile_dir):
     65     os.mkdir(logfile_dir)
     66 
     67 # log文件的全路径
     68 logfile_path = os.path.join(logfile_dir, logfile_name)
     69 
     70 # log配置字典
     71 LOGGING_DIC = {
     72     'version': 1,
     73     'disable_existing_loggers': False,
     74     'formatters': {
     75         'standard': {
     76             'format': standard_format
     77         },
     78         'simple': {
     79             'format': simple_format
     80         },
     81     },
     82     'filters': {},
     83     'handlers': {
     84         #打印到终端的日志
     85         'console': {
     86             'level': 'DEBUG',
     87             'class': 'logging.StreamHandler',  # 打印到屏幕
     88             'formatter': 'simple'
     89         },
     90         #打印到文件的日志,收集info及以上的日志
     91         'default': {
     92             'level': 'DEBUG',
     93             'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件
     94             'formatter': 'standard',
     95             'filename': logfile_path,  # 日志文件
     96             'maxBytes': 1024*1024*5,  # 日志大小 5M
     97             'backupCount': 5,
     98             'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了
     99         },
    100     },
    101     'loggers': {
    102         #logging.getLogger(__name__)拿到的logger配置
    103         '': {
    104             'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
    105             'level': 'DEBUG',
    106             'propagate': True,  # 向上(更高level的logger)传递
    107         },
    108     },
    109 }
    110 
    111 
    112 def load_my_logging_cfg():
    113     logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
    114     logger = logging.getLogger(__name__)  # 生成一个log实例
    115     logger.info('It works!')  # 记录该文件的运行状态
    116 
    117 if __name__ == '__main__':
    118     load_my_logging_cfg()
    119 
    120 #=============>core目录:存放核心逻辑
    121 #core.py
    122 import logging
    123 import time
    124 from conf import settings
    125 from lib import read_ini
    126 
    127 config=read_ini.read(settings.config_path)
    128 logger=logging.getLogger(__name__)
    129 
    130 current_user={'user':None,'login_time':None,'timeout':int(settings.user_timeout)}
    131 def auth(func):
    132     def wrapper(*args,**kwargs):
    133         if current_user['user']:
    134             interval=time.time()-current_user['login_time']
    135             if interval < current_user['timeout']:
    136                 return func(*args,**kwargs)
    137         name = input('name>>: ')
    138         password = input('password>>: ')
    139         if config.has_section(name):
    140             if password == config.get(name,'password'):
    141                 logger.info('登录成功')
    142                 current_user['user']=name
    143                 current_user['login_time']=time.time()
    144                 return func(*args,**kwargs)
    145         else:
    146             logger.error('用户名不存在')
    147 
    148     return wrapper
    149 
    150 @auth
    151 def buy():
    152     print('buy...')
    153 
    154 @auth
    155 def run():
    156 
    157     print('''
    158 购物
    159 查看余额
    160 转账
    161     ''')
    162     while True:
    163         choice = input('>>: ').strip()
    164         if not choice:continue
    165         if choice == '1':
    166             buy()
    167 
    168 
    169 
    170 if __name__ == '__main__':
    171     run()
    172 
    173 #=============>db目录:存放数据库文件
    174 #alex_json
    175 #egon_json
    176 
    177 #=============>lib目录:存放自定义的模块与包
    178 #read_ini.py
    179 import configparser
    180 def read(config_file):
    181     config=configparser.ConfigParser()
    182     config.read(config_file)
    183     return config
    184 
    185 #=============>log目录:存放日志
    186 #all2.log
    187 [2017-07-29 00:31:40,272][MainThread:11692][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
    188 [2017-07-29 00:31:41,789][MainThread:11692][task_id:core.core][core.py:25][ERROR][用户名不存在]
    189 [2017-07-29 00:31:46,394][MainThread:12348][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
    190 [2017-07-29 00:31:47,629][MainThread:12348][task_id:core.core][core.py:25][ERROR][用户名不存在]
    191 [2017-07-29 00:31:57,912][MainThread:10528][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
    192 [2017-07-29 00:32:03,340][MainThread:12744][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
    193 [2017-07-29 00:32:05,065][MainThread:12916][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
    194 [2017-07-29 00:32:08,181][MainThread:12916][task_id:core.core][core.py:25][ERROR][用户名不存在]
    195 [2017-07-29 00:32:13,638][MainThread:7220][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
    196 [2017-07-29 00:32:23,005][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
    197 [2017-07-29 00:32:40,941][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
    198 [2017-07-29 00:32:47,222][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
    199 [2017-07-29 00:32:51,949][MainThread:7220][task_id:core.core][core.py:25][ERROR][用户名不存在]
    200 [2017-07-29 00:33:00,213][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
    201 [2017-07-29 00:33:50,118][MainThread:8500][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
    202 [2017-07-29 00:33:55,845][MainThread:8500][task_id:core.core][core.py:20][INFO][登录成功]
    203 [2017-07-29 00:34:06,837][MainThread:8500][task_id:core.core][core.py:25][ERROR][用户名不存在]
    204 [2017-07-29 00:34:09,405][MainThread:8500][task_id:core.core][core.py:25][ERROR][用户名不存在]
    205 [2017-07-29 00:34:10,645][MainThread:8500][task_id:core.core][core.py:25][ERROR][用户名不存在]
    常用模块的使用
  • 相关阅读:
    concrete maths ch4 number theory
    Aho-Corasick algorithm
    Finding repetitions
    Suffix Automaton
    Z-function and its calculation
    mongodb安装与启动
    centos redis 集群搭建
    nginx实现热部署(平滑升级)
    nacos集群部署安装
    springboot+zookeeper+dubbo整合
  • 原文地址:https://www.cnblogs.com/happy-king/p/7676794.html
Copyright © 2011-2022 走看看