Day5 函数递归,匿名、内置行数,模块和包,开发规范
一、递归与二分法
一、递归
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、递归的执行分为两个阶段:递推(询问的过程)和回溯(回答的过程)
- #获知age(5)的值
- # age(5)=age(4)+2
- # age(4)=age(3)+2
- # age(3)=age(2)+2
- # age(2)=age(1)+2
- # age(1)=18
- #
- # age(n)=age(n-1)+2 #n>1
- # age(1)=18 #n=1
- def age(n):
- if n == 1:
- return 18
- return age(n-1)+2
- print(age(5))
5、可以递归的最大深度
- #虽然可以设置,但是因为不是尾递归,仍然要保存栈,内存大小一定,不可能无限递归
- import sys
- sys.getrecursionlimit() ##获取目前默认递归的最大深度,默认深度是1000
- sys.setrecursionlimit(500) ##更改默认递归的最大深度
- n=1
- def test():
- global n
- print(n)
- n+=1
- test()
- 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、 二分法的作用:不断将列表切分成两份,减小压力
- l = [1,2,5,6,77,1001,1165,2340]
- def search(l,num):
- print(l)
- if len(l) > 1:
- mid_index = len(l) // 2 #相除取整
- if num > l[mid_index]:
- #in the right
- l = l[mid_index+1:]
- elif num < l[mid_index]:
- #in the left
- l = l[:mid_index]
- else:
- print('find it')
- return
- else:
- if l[0] == num:
- print('find it')
- else:
- print('not exists')
- return
- search(l,num)
- 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+'',l)))
4、reduce(合并)与lambda结合
计算0到100数字的和
- from functools import reduce
- # reduce(lambda 表达式,计算范围,计算的初始值)
- res=reduce(lambda x,y:x+y,range(1,100),100)
- print(res)
5、filter(过滤)与lambda结合
过滤出列表中以123结尾的元素
- l=['alex123','egon123','wzs123','yuanhao']
- print(list(filter(lambda name:name.endswith(''),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])
- t1=(111,'a')
- t2=(11,'b',123,'c')
- 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("") # 转换为整数 integer
- float(2) # 转换为浮点数 float
- long("") # 转换为长整数 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) # 切片操作
- # bytes object
- b = b"example"
- # str object
- s = "example"
- # str to bytes
- sb = bytes(s, encoding = "utf8")
- print(type(sb))
- # bytes to str
- bs = str(b, encoding = "utf8")
- # an alternative(可替代的方法) method
- # str to bytes
- sb2 = str.encode(s)
- # bytes to str
- 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]])
举例
- s1="1+2+3"
- # s1="['a','b','c']"
- s2="for i in range(10):print (i)"
- print(eval(s1))
- print(exec(s1))
- 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、更改模块的功能
测试文件
- def sqlparse():
- print('mysql sqlparse')
mysql.py
- def sqlparse():
- print('oracle sqlparse')
oracle.py
导入模块,并执行
- import spam as s1
- money = 10000000
- spam.change()
- print(spam.money)
模块名比较长
- sql_type = input('sql_type>>')
- if sql_type == 'mysql':
- import mysql as sql ##引用不同的模块,因为实现的功能是相同的,所以可以起相同的别名
- elif sql_type == 'oracle':
- import oracle as sql
- sql.sqlparse()
传入的内容调用不同的模块
3、导入多个模块:模块之间用逗号隔开(不建议这么写,还是不同模块分行写为好)
- import os,sys,requests
4、模块导入的特点
模块只在第一次导入时才会执行,之后的导入都是直接引用内存已经存在的结果
- import spam
- import spam
- import spam
- import spam
- #验证是否已经在内存
- import sys
- # print(sys.modules) #存放的是已经加到内存的模块
- print('spam' in sys.modules) #查看一个模块是否加到内存中
- import spam
- print('spam' in sys.modules)
导入,并验证是否已在内存中
三、from....import...导入模块
1、对比import导入模块,from....import...的优缺点
- 对比import spam,会将源文件的名称空间'spam'带到当前名称空间中,使用时必须是spam.名字的方式
- 而from 语句相当于import,也会创建新的名称空间,但是将spam中的名字直接导入到当前的名称空间中,在当前名称空间中,直接使用名字就可以了
- 优点:使用源文件内的名字时,无需加前缀,使用方便
- 缺点:容易与当前文件的名称空间内的名字混淆,会覆盖原来名字的值
2、语法范例
- from spam import money,read1,read2
- money = 10
- print(money)
- # g=read1()
- g=read2()
- 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:\data\PyCharm_Project\s19\day5\模块\模块的搜索路径\aaa')
- # 加到最前面
- sys.path.insert(0,r'G:\data\PyCharm_Project\s19\day5\模块\模块的搜索路径\aaa')
- import spam
- from aaa import #模块的搜索路径
五、模块的重载
考虑到性能的原因,每个模块只被导入一次,放入字典sys.module中,如果你改变了模块的内容,你必须重启程序,python不支持重新加载或卸载之前导入的模块
有的同学可能会想到直接从sys.module中删除一个模块不就可以卸载了吗,注意了,你删了sys.module中的模块对象仍然可能被其他程序的组件所引用,因而不会被清楚。
特别的对于我们引用了这个模块中的一个类,用这个类产生了很多对象,因而这些对象都有关于这个模块的引用。
如果只是你想交互测试的一个模块,使用 importlib.reload(), e.g. import importlib; importlib.reload(modulename),这只能用于测试环境。
- def func1():
- print('func1')
aa.py
- import time,importlib
- import aa
- time.sleep(20)
- # importlib.reload(aa)
- 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、注意事项
- .关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。
- .对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
- .对比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
二、包的使用
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:\Users\CTB-BJB-0012\PycharmProjects\python36\s19\day5\包\xxx\yyy')
- import aaa
- from .m1 import func1
- from .m2 import func2
- from .bbb.m3 import func3
- from .bbb.m3 import func4
aaa同级的__init__.py内容
- from ..ccc.m4 import func4
- def func3():
- print('f3')
- func4()
m3.py文件内容
- import sys
- sys.path.append(r'C:\Users\CTB-BJB-0012\PycharmProjects\python36\s19\day5\包\xxx\yyy')
- import aaa
- aaa.func1()
- aaa.func2()
- aaa.func3()
运行run.py文件内容
运行文件使用import直接导入所需模块的功能(使用了解目录结构):
导入:import aaa.ccc.m4
调用:aaa.ccc.c4.func4()
6、包的分发(了解)
学习链接网址:https://packaging.python.org/tutorials/distributing-packages/
六、软件开发规范
一、软件目录规范如下
二、常用模块的使用
- #=============>bin目录:存放执行脚本
- #start.py
- import sys,os
- BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
- sys.path.append(BASE_DIR)
- from core import core
- from conf import my_log_settings
- if __name__ == '__main__':
- my_log_settings.load_my_logging_cfg()
- core.run()
- #=============>conf目录:存放配置文件
- #config.ini
- [DEFAULT]
- user_timeout = 1000
- [egon]
- password = 123
- money = 10000000
- [alex]
- password = alex3714
- money=10000000000
- [yuanhao]
- password = ysb123
- money=10
- #settings.py
- import os
- config_path=r'%s\%s' %(os.path.dirname(os.path.abspath(__file__)),'config.ini')
- user_timeout=10
- user_db_path=r'%s\%s' %(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),\
- 'db')
- #my_log_settings.py
- """
- logging配置
- """
- import os
- import logging.config
- # 定义三种日志输出格式 开始
- standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
- '[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字
- simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
- id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
- # 定义日志输出格式 结束
- logfile_dir = r'%s\log' %os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # log文件的目录
- logfile_name = 'all2.log' # log文件名
- # 如果不存在定义的日志目录就创建一个
- if not os.path.isdir(logfile_dir):
- os.mkdir(logfile_dir)
- # log文件的全路径
- logfile_path = os.path.join(logfile_dir, logfile_name)
- # log配置字典
- LOGGING_DIC = {
- 'version': 1,
- 'disable_existing_loggers': False,
- 'formatters': {
- 'standard': {
- 'format': standard_format
- },
- 'simple': {
- 'format': simple_format
- },
- },
- 'filters': {},
- 'handlers': {
- #打印到终端的日志
- 'console': {
- 'level': 'DEBUG',
- 'class': 'logging.StreamHandler', # 打印到屏幕
- 'formatter': 'simple'
- },
- #打印到文件的日志,收集info及以上的日志
- 'default': {
- 'level': 'DEBUG',
- 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件
- 'formatter': 'standard',
- 'filename': logfile_path, # 日志文件
- 'maxBytes': 1024*1024*5, # 日志大小 5M
- 'backupCount': 5,
- 'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
- },
- },
- 'loggers': {
- #logging.getLogger(__name__)拿到的logger配置
- '': {
- 'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
- 'level': 'DEBUG',
- 'propagate': True, # 向上(更高level的logger)传递
- },
- },
- }
- def load_my_logging_cfg():
- logging.config.dictConfig(LOGGING_DIC) # 导入上面定义的logging配置
- logger = logging.getLogger(__name__) # 生成一个log实例
- logger.info('It works!') # 记录该文件的运行状态
- if __name__ == '__main__':
- load_my_logging_cfg()
- #=============>core目录:存放核心逻辑
- #core.py
- import logging
- import time
- from conf import settings
- from lib import read_ini
- config=read_ini.read(settings.config_path)
- logger=logging.getLogger(__name__)
- current_user={'user':None,'login_time':None,'timeout':int(settings.user_timeout)}
- def auth(func):
- def wrapper(*args,**kwargs):
- if current_user['user']:
- interval=time.time()-current_user['login_time']
- if interval < current_user['timeout']:
- return func(*args,**kwargs)
- name = input('name>>: ')
- password = input('password>>: ')
- if config.has_section(name):
- if password == config.get(name,'password'):
- logger.info('登录成功')
- current_user['user']=name
- current_user['login_time']=time.time()
- return func(*args,**kwargs)
- else:
- logger.error('用户名不存在')
- return wrapper
- @auth
- def buy():
- print('buy...')
- @auth
- def run():
- print('''
- 购物
- 查看余额
- 转账
- ''')
- while True:
- choice = input('>>: ').strip()
- if not choice:continue
- if choice == '':
- buy()
- if __name__ == '__main__':
- run()
- #=============>db目录:存放数据库文件
- #alex_json
- #egon_json
- #=============>lib目录:存放自定义的模块与包
- #read_ini.py
- import configparser
- def read(config_file):
- config=configparser.ConfigParser()
- config.read(config_file)
- return config
- #=============>log目录:存放日志
- #all2.log
- [2017-07-29 00:31:40,272][MainThread:11692][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
- [2017-07-29 00:31:41,789][MainThread:11692][task_id:core.core][core.py:25][ERROR][用户名不存在]
- [2017-07-29 00:31:46,394][MainThread:12348][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
- [2017-07-29 00:31:47,629][MainThread:12348][task_id:core.core][core.py:25][ERROR][用户名不存在]
- [2017-07-29 00:31:57,912][MainThread:10528][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
- [2017-07-29 00:32:03,340][MainThread:12744][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
- [2017-07-29 00:32:05,065][MainThread:12916][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
- [2017-07-29 00:32:08,181][MainThread:12916][task_id:core.core][core.py:25][ERROR][用户名不存在]
- [2017-07-29 00:32:13,638][MainThread:7220][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
- [2017-07-29 00:32:23,005][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
- [2017-07-29 00:32:40,941][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
- [2017-07-29 00:32:47,222][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
- [2017-07-29 00:32:51,949][MainThread:7220][task_id:core.core][core.py:25][ERROR][用户名不存在]
- [2017-07-29 00:33:00,213][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
- [2017-07-29 00:33:50,118][MainThread:8500][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
- [2017-07-29 00:33:55,845][MainThread:8500][task_id:core.core][core.py:20][INFO][登录成功]
- [2017-07-29 00:34:06,837][MainThread:8500][task_id:core.core][core.py:25][ERROR][用户名不存在]
- [2017-07-29 00:34:09,405][MainThread:8500][task_id:core.core][core.py:25][ERROR][用户名不存在]
- [2017-07-29 00:34:10,645][MainThread:8500][task_id:core.core][core.py:25][ERROR][用户名不存在]
常用模块的使用
Day5 函数递归,匿名、内置行数,模块和包,开发规范的更多相关文章
- py基础3--函数,递归,内置函数
本节内容 函数基本语法及特性 参数与局部变量 返回值 嵌套函数 递归 匿名函数 函数式编程介绍 高阶函数 内置函数 1. 函数基本语法及特性 背景提要 现在老板让你写一个监控程序,监控服务器的系统状况 ...
- python自动化day3-函数、递归、内置函数
一.什么是函数 修理工===>程序员 具备某一功能的工具===>函数 要想使用工具,需要事先准备好,然后拿来就用且可以重复使用要想用函数,需要先定义,再使用 二.函数基础 1.函数分类 # ...
- 简学Python第三章__函数式编程、递归、内置函数
#cnblogs_post_body h2 { background: linear-gradient(to bottom, #18c0ff 0%,#0c7eff 100%); color: #fff ...
- 生成器的send方法、递推函数、匿名函数及常用内置函数
生成器的send方法 在使用yield方法创建生成器时,不仅可以使用next方法进行取值,还可以通过send方法向生成器的内部传值 什么是send方法? send方法相当于高级的next方法,send ...
- python 函数 装饰器 内置函数
函数 装饰器 内置函数 一.命名空间和作用域 二.装饰器 1.无参数 2.函数有参数 3.函数动态参数 4.装饰器参数 三.内置函数 salaries={ 'egon':3000, 'alex':10 ...
- 【Android】9.2 内置行视图的分类和呈现效果
分类:C#.Android.VS2015: 创建日期:2016-02-18 一.简介 Android内置了很多行视图模板,在应用程序中可直接使用这些内置的视图来呈现列表项. 要在ListView中使用 ...
- JavaScript封装一个函数效果类似内置方法concat()
JavaScript封装一个函数效果类似内置方法concat() 首先回忆concat()的作用: concat() 方法用于连接两个或多个数组.该方法不会改变现有的数组,而仅仅会返回被连接数组的一个 ...
- Python内置的操作系统模块(os)与解释器交互模块(sys)
Python内置的操作系统模块(os)与解释器交互模块(sys) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本片博客只介绍Python调用操作系统的模块即os模块,以及Pyth ...
- Filebeat使用内置的mysql模块收集日志存储到ES集群并使用kibana存储
Filebeat内置了不少的模块,可以直接使用他们对日志进行收集,支持的模块如下: [root@ELK-chaofeng07 logstash]# filebeat modules list Enab ...
随机推荐
- 如何用VBA实现格式刷的功能?
1. http://club.excelhome.net/thread-373686-1-1.html 复制1格式Selection.CopyFormat粘贴格式Selection.PasteForm ...
- springMVC参数传递实例
最好所有的post请求用postman这个工具就好了. postman传对象
- ajax 获取服务器返回的XML字符串
前台 解析失败不会抛出任何异常, 只会返回一个给定的错误文档 let l = console.log let http = ajanuw.create({ uri: 'http://localhost ...
- Smarty模板保留缓存
<?php //缓存 //注:使用缓存需要用到这几个方法: //(ob_start(开启内存缓存); ob_flush(清除内存缓存);) //file_exists这个方法是判断文件是否存在 ...
- Ajax请求参数较长导致请求失败
Ajax请求参数比较长,第5行参数大概1100个字符吧,是接口的请求报文. $.ajax({ type:"POST", url:"${ctx}/test.action?m ...
- [No0000128]SQL纵表与横表互转
1.纵表转横表: 纵表结构:Table1 转换后的横表结构: Sql示例代码: select username, sum(case Course when '语文' then Grade else 0 ...
- GlusterFS分布式存储系统中更换故障Brick的操作记录1
前面已经介绍了GlusterFS分布式存储集群环境部署记录,现在模拟下更换故障Brick的操作: 1)GlusterFS集群系统一共有4个节点,集群信息如下: 分别在各个节点上配置hosts.同步好系 ...
- LU decomposition can be viewed as the matrix form of Gaussian elimination.
https://en.wikipedia.org/wiki/LU_decomposition One way to find the LU decomposition of this simple m ...
- A Method for the Construction of Minimum-Redundancy Codes
A Method for the Construction of Minimum-Redundancy Codes http://compression.ru/download/articles/hu ...
- Xcode报错Expected selector for Objective-C and Expected method body
昨天把键盘拿起来拍一下清清灰,然后就发现Xcode报错了,Xcode报错Expected selector for Objective-C and Expected method body,也不知道什 ...