递归
1.必须有明确结束条件
2.每次进入递归,问题必须比上一次缩小
3.效率不高,递归层数过多就导致栈(内存)溢出
递归=递推+回溯
递归默认层数1000层
import sys print(sys.getrecursionlimit()) #看递归最大值 #1000 print(sys.setrecursionlimit(100000)) #更改递归最大值为100000 print(sys.getrecursionlimit()) #再次查看 #100000
实例:查年龄
#题目:共5人,已知我18岁,求第5人年龄 #如果n不等于1 执行递推(5-1)+2=(4-1)+2= (3-1)+2=(2-1)+2=1 # 现在1=n执行 执行回溯2+2+2+2+18=26 def age(n): if n==1: return 18 return age(n-1)+2 print(age(5)) #26
二分法
#从N个有序数据中找到想要的值,注:无序不能查找
data = range(1,4200000000) #定义一个1至4200000000的数 def binary_search(find_str,data_set,count): mid = int(len(data_set)//2) #每次除以data长度的一半 if data_set[mid] == find_str: #如果找到find_str(查找的值) print("find it",find_str,"查找次数",count) #显示查找值和查找次数 elif data_set[mid] > find_str: #如果值大于查找值 print("在左边 ",data_set[mid],data_set[0:mid]) #显示当前值,显示查询范围 binary_search(find_str,data_set[0:mid],count+1) #再次递归,在查询范围中再次查询,计数器+1 else: #如果值小于查找值 print("在右边 ",data_set[mid], data_set[mid+1:]) #显示当前值,显示查询范围 binary_search(find_str, data_set[mid+1:],count+1) #再次递归,在查询范围中再次查询,计数器+1 binary_search(13354240, data,0) #13354240是查找数 调用data函数值,0是计数器
模块调用
模块的搜索顺序: 内存--内置--sys.path(环境变量)
导入模块要做的3件事
1.创建新的作用域
2.在该作用域中执行顶级代码
3.得到一个模块名,绑定到该模块内的代码
#模块更新不会影响到已经使用的文件,因为文件之前已经把该模块写入到内存,
#模块导入一次就导入到内存,多次导入只是从内存中读取
定义模块 python文件名是spam
__all__=["money","read1"] #本模块中能这调用money和read1,只针对from ... ipmprt * 形式, aa=("form modue spam") money=100 money1=10000 def read1(): print(money) def read2(): print(money1) if __name__=="__main__": #如果条件成立,可继续写条件操作,主要用于测试环境测试该脚本 #__name__是本文件的名字 __main__是以脚本形式调用的该文件 #如果__name__的值不是__main__,说明该文件是被当做模块调用的形式使用 print("该文件被当做脚本文件执行"
新建立个python,作用:调用上边的模块
import
#直接调用模块 import spam #调用模块 import spam as sm #定义spam别名为sm print(spam.aa) #显示模块中的aa变量 #form modue spam print(sm.aa) #显示模块中的aa变量 #form modue spam spam.read1() #调用模块中的函数 #100
from ... import ...
#调用指定模块的变量或函数,调用时不用指定模块名 from spam import read1,aa #调用spam模块的read1函数和aa变量 #from spaa import read1 #注意不同模块的同名函,下边模块中函数会覆盖上边模块中函数 from spam import read1 as read #创建别名,如此调用spam的read1就使用read就和spaa不冲突了 read1() #100 print(aa) #form modue spam #注意,如果在本文件中定义函数read1 会显示本文件中的函数,而不是模块中的read1 def read1(): aa=("aa11") return aa print(read1()) #aa11
from ... import *
#调用sapm模块总不以_开头的名字,全部可调用 #建议不用,因为不知道模块中的值是否会和本文件冲突, #如果要用看模块调用的__all__ 可以错开这个问题(看上边的定义模块) read1() #100 print(money) #100 print(money) #会报错 因为在模块中定义了__all__
包
包针对模块导入的功能
包(目录)是一种通过使用模块名来组织python模块名称空间的方式
模块导入的时候,只要是遇到"."的都是包导入,注"."的左边边必须是一个包(目录)
__init__
作用:初始化包的代码,
#只要导入包,就会依次执行包下的__init__py文件,再执行包下的py文件或包下的子包 #__init__.py默认创建, __init__.py可以为空,也可以存放初始化包的代码 #__init__同级有cc.py __all__=["cc","money","read1"] #可以使用cc.py,money变量,dd函数,只针对from ... ipmprt * 形式, print("==hello==") x=1 money=100 money1=1000 def dd(): print(money)
import 导入
主要用途导入内置模块 import aa.db.cc #.的左边必须是包 aa和db是包 cc是py文件 aa.db.cc.dd() #dd是函数 # import aa.db.cc as e #cc创建别名为e # e.dd() #再次调用e.py,不用写路径
from..import...模式导入
绝对路径导入和相对路径导入
#主要用于导入自己创建子包, #针对form后import导入模块,必须不能带.(点),否则会语法错误 #例如from aa.db import cc.dd (dd文件和dd函数同时在import后边就会报错) #这是绝对路径导入(cc.py文件可以调用db包下其他py文件,import模式就需要加入path路径) from aa.db.cc import dd #dd是cc.py下的函数 dd() #这是相对导入(..是上层目录,就是调用上层目录下的db包的cc.py文件) from ..db.cc import dd dd() #单独导入 #当前目录导入 from .db import cc #当前目录导入, 和db在同级目录,调用cc.py
软件目录开发规范
item #程序主体
bin #存放执行脚本
conf #配置文件
core #核心逻辑
db #db存放
lib #存放自定义的模块与包
log #存放日志
log日志模块
loggin模块
分5个级别 debug() info() warnging() error() critical()
日志级别
- CRITICAL = 50
- ERROR = 40
- WARNING = 30
- INFO = 20
- DEBUG = 10
- NOTSET = 0
日志格式
%(name)s |
Logger的名字 |
%(levelno)s |
数字形式的日志级别 |
%(levelname)s |
文本形式的日志级别 |
%(pathname)s |
谁调用日志输出该函数的模块的完整路径名,可能没有 |
%(filename)s |
谁调用日志输出该函数的模块的文件名(aa.py) |
%(module)s |
谁调用日志输出该函数的模块名(aa) |
%(funcName)s |
谁调用日志输出该函数的函数名 |
%(lineno)d |
谁调用日志输出该函数的语句所在的代码行 |
%(created)f |
当前时间,用UNIX标准的表示时间的浮 点数表示 |
%(relativeCreated)d |
输出日志信息时的,自Logger创建以 来的毫秒数 |
%(asctime)s |
字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒 |
%(thread)d |
线程ID。可能没有 |
%(threadName)s |
线程名。可能没有 |
%(process)d |
进程ID。可能没有 |
%(message)s |
用户输出的消息 |
简写日志方式
import logging logging.basicConfig(filename='access.log', #日志保存位置.默认当前 format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',#格式 datefmt='%Y-%m-%d %H:%M:%S %p',#时间 level=10)#打印日志等级 #默认打印到终端 logging.debug('debug') logging.info('info') logging.warning('warning') logging.error("error") logging.critical("scritical")
日志定义
import logging formatter=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p',) #FileHandler 日志保存位置 fh1=logging.FileHandler('test1.log')
#StreamHandler打印日志到终端 ch=logging.StreamHandler()
#日志格式传入日志保存位置 fh1.setFormatter(formatter) #也可以是不同的formater(日志格式) ch.setFormatter(formatter) #setFormatter级别 定义日志介绍级别 ch.setLevel(10) #2个级别都满足日志日志,这个可不写,用处不大 #getLogger 指定日志用户并产生日志 logger=logging.getLogger("guolm") #logger1=logging.getLogger("guolm") #指定guolm 默认对象是root
#设置日志级别 logger.setLevel(10) #在getLongger定义日志级别 10是debug 20是INFO 30是WARNING 40是ERROR 50是CRITICAL #把日志放到日志文件 logger.addHandler(fh1) logger.addHandler(ch)
#能打印哪些日志 logger.debug('debug') logger.info('info') logger.warning('warning') logger.error('error') logger.critical('critical')