一、字符转格式化
在python 中目前使用的字符串格式化有两种 % ,format;建议使用format方式,百分号方式是比较古老的,而format方式比较新,相比百分号方式功能较全,有替换古老方式的趋势,目前并存。
1、百分号方式:
%[(name)][flags][width].[precision]typecode
name 可选, 用于选择指定的key
flages 可选,可提供选择值有:
辅助符号 | 说明 |
- | 用做左对齐;正数前无符号,负数前加符号 |
+ | 在右对齐;正数前加正号,负数前加负号 |
0 | 显示的数字前面填充“0”而不是默认的空格 |
格式化符号 | 说明 |
%s | 优先用str()函数进行字符串转换,并格式化的指定位置 |
%d | 转成十进制数,并格式化的指定位置 |
%o | 转成八进制数,并格式化的指定位置 |
%x |
转成十六进制数,并格式化的指定位置 |
%e/%E | 转成科学计数法,并格式化的指定位置(e,E就是输出的时候大小写区别) |
%c | 将十进制数转换为其unicode对应的值是字符,并把字符添加到指定位置 |
%f/%F | 转成浮点型,并格式化的指定位置(默认保留小数点后6位) |
%g/%G | 自动调整将整数,浮点数转换成浮点或科学计数法(超过6位数用科学计数法) |
% | 字符串中出现占位符,两个%表示一个%,不出现占位符,就无所谓 |
width :表示占有宽度
下面列举了几个例子:
1 test1="my name is %s" %"xiaoma" 2 print(test1) 3 #结果 4 my name is xiaoma 5 6 test2="my name is %s age%d" %("tianjie",18) 7 print(test2) 8 #结果 9 my name is tianjie age18 10 11 test3="my name is %(name)s , age %(age)d" %{"name":"dbq","age":18} 12 print(test3) 13 #结果 14 my name is dbq , age 18 15 16 test4="percent %.2f" %89.123345 #保留两位小数点 17 print(test4) 18 #结果 19 percent 89.12 20 21 test5="percent %(xiao).2f %%" %{"xiao":123.1233465} 22 #一个百分号会报错的 23 print(test5) 24 #结果 25 percent 123.12 % 26 27 charA = 65 28 charB = 66 29 print("ASCII码65代表:%c" % charA) 30 print("ASCII码66代表:%c" % charB) 31 Num1 = 0xEF3 32 Num2 = 0xAB03 33 print('转换成十进制分别为:%u和%u' % (Num1, Num2)) 34 Num3 = 1200000 35 print('转换成科学计数法为:%e' % Num3) 36 37 #输出结果: 38 ASCII码65代表:A 39 ASCII码66代表:B 40 转换成十进制分别为:3827和43779 41 转换成科学计数法为:1.200000e+06
注意:百分号方式没有二进制转换方式,
2、format格式化方式
字符串的参数使用{NUM}进行表示,0, 表示第一个参数,1, 表示第二个参数, 以后顺次递加;
使用":", 指定代表元素需要的操作, 如":.3"小数点三位, ":8"占8个字符空间等
还可以添加特定的字母, 如:
'b' - 二进制. 将数字以2为基数进行输出.
'c' - 字符. 在打印之前将整数转换成对应的Unicode字符串.
'd' - 十进制整数. 将数字以10为基数进行输出.
'o' - 八进制. 将数字以8为基数进行输出.
'x' - 十六进制. 将数字以16为基数进行输出, 9以上的位数用小写字母.
'e' - 幂符号. 用科学计数法打印数字, 用'e'表示幂.
'g' - 一般格式. 将数值以fixed-point格式输出. 当数值特别大的时候, 用幂形式打印.
'n' - 数字. 当值为整数时和'd'相同, 值为浮点数时和'g'相同. 不同的是它会根据区域设置插入数字分隔符.
'%' - 百分数. 将数值乘以100然后以fixed-point('f')格式打印, 值后面会有一个百分号.
数字(0, 1, ...)即代表format()里面的元素, 所以可以使用"."调用元素的方法;
还有一些辅助符号:
<,左对齐
>,右对齐
^,内容居中
=,内容右对齐,将符号放置在填充字符的左侧,且只对数字类型有效。
还是看一下实际运用更加一目了然:
1 for1="my name is {},age {},job {}".format("dbp",18,"IT") 2 print(for1) 3 #执行结果 4 my name is dbp,age 18,job IT 5 6 for2="my name is {},age {},job {}".format(*["dbp",18,"IT"]) 7 #后面加*表示也可以导入一个列表变量 8 print(for2) 9 #执行结果 10 my name is dbp,age 18,job IT 11 12 for3 = "my name is {0},age {1},job {0}".format("qqq",18) 13 #可以根据索引值调用 14 print(for3) 15 #执行结果 16 my name is qqq,age 18,job qqq 17 18 for4="my name is {name},age {age},job {job} ".format(**{"name":"tianjie","age":19,"job":"IT"}) 19 #加两个* 可以导入字典,根据key调用 20 print(for4) 21 #执行结果 22 my name is tianjie,age 19,job IT 23 24 for5="my name is {0[0]},age {0[1]},job {1[2]}".format(["tianjie",123,"hello"],["dbq","banking",234]) 25 print(for5) 26 #执行结果 27 my name is tianjie,age 123,job 234 28 29 for6="my name is {:s},age {:d},money {:f}".format("tianjie",18,2222.1) 30 #字符、整数、浮点数 31 print(for6) 32 #执行结果 33 my name is tianjie,age 18,money 2222.100000 34 35 for7="i am {name:s}, age {age:d}, job {job:s}".format(**{"name": "admin", "age": 18,"job":"banking"}) 36 print(for7) 37 #执行结果 38 i am admin, age 18, job banking 39 40 for8="numbers: {:#b},{:#o},{:#d},{:#x},{:#X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2) 41 print(for8) 42 #转换为二进制、八进制、十六进制、百分数(不加#表示显示结果没有0b、0o、0x) 43 numbers: 0b1111,0o17,15,0xf,0XF, 1587.623000% 44 45 for9="numbers: {0:#b},{0:#o},{0:#d},{0:#x},{1:#X}, {2:%}".format(15,56,0.9897763) 46 print(for9) 47 #执行结果 48 numbers: 0b1111,0o17,15,0xf,0X38, 98.977630%
二、迭代器,生成器,递归
1、迭代器
刚开始的时候一直认为,可以被 for循环的的对象,就为迭代器,下面是更严谨的解释!
迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退。另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件
特点:
- 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
- 不能随机访问集合中的某个值 ,只能从头到尾依次访问
- 访问到一半时不能往回退
- 便于循环比较大的数据集合,节省内存
总之就是,可以通过_next_去取,需要一个取一个,而不是把元素,一整个加进内存,你可以迭代不是序列但表现处序列行为的对象,例如字典的键、一个文件的行,或者一个字符串!如以下事例:
1 name=iter("hello") 2 print(name.__next__()) 3 print(name.__next__()) 4 print(name.__next__()) 5 print(name.__next__()) 6 print(name.__next__()) 7 8 #执行结果 9 h 10 e 11 l 12 l 13 o
2、生成器
一个函数调用时返回一个迭代器,那这个函数就叫生成器(generator),只要看到函数中出现yield,那么这个函数就是生成器;如以下实例:
1 import time 2 def func(num): 3 a=0 4 while True: 5 a+=1 6 if a>=num: 7 return 8 else: 9 yield a 10 11 test=func(5) 12 print(test) 13 for i in test: 14 print(i) 15 time.sleep(1) #停一秒在显示 16 17 #执行结果 18 <generator object func at 0x0000003668194A40> 19 1 20 2 21 3 22 4
3、递归
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。
递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
使用递归函数需要注意防止栈溢出,不能写入死的循环没有结束值。
如示例:计算斐波那契数列0,1,1,2,3,5,8,13,21,34,55,89.。。。。。。
1 def func(arg1,arg2,stops): 2 if arg1==0: 3 print(arg1,arg2) 4 arg3=arg1+arg2 5 print(arg3) 6 if arg3<stops: 7 func(arg2,arg3,stops) 8 else: 9 return 10 11 func(0,1,20) #结束值20 12 #执行结果 13 0 1 14 1 15 2 16 3 17 5 18 8 19 13 20 21
练习实例:
用递归计算1*2*3*4*5*6*7结果:
1 def func(num): 2 if num==1: 3 return num 4 else: 5 return num * func(num-1) 6 print(func(7)) 7 8 #执行过程 9 10 # func(7) 11 # 7*func(6) 12 # 7*(6*func(5)) 13 # 7*(6*(5*func(4))) 14 # 7*(6*(5*(4*func(3)))) 15 # 7*(6*(5*(4*(3*func(2))))) 16 # 7*(6*(5*(4*(3*(2*(func(1))))))) 17 # 7*(6*(5*(4*(3*(2*1))))) 18 # 7*(6*(5*(4*(3*2)))) 19 # 7*(6*(5*(4*6))) 20 # 7*(6*(5*24)) 21 # 7*(6*120) 22 # 7*720 23 # 5040
三、模块
随着代码越写越多,功能越来越多,你不能把所有的代码都写在一个文件中,不方便查询排错,那么我们就想着把一个功能放在一个文件中,或者一个函数。
在python中一个.py的文件就称之为一个模块;在其他语言中如Java、c# 等叫做类库。
模块有三种:
内置模块
第三方模块
自定义模块
1.自定义模块
自定义模块,就是根据功能需求自己写的py文件,供功能调用
要想使用模块首先要导入模块,下面列举几个导入模块的例子:
1 # import digui 2 # 3 # digui.login() 4 # 5 # from test import mokuai 6 # from test import mokuai as rename 7 # from test import file 8 # import test_ll.file 9 # test_ll.file.func() 10 # # mokuai.func(3) 11 import requests
导入模块时是根据哪个路径作为基准来进行的呢:sys.path
1 import sys 2 print(sys.path) 3 #返回结果 4 ['E:\python课程\day5', 5 'E:\python课程', 6 7 'C:\Users\Administrator\AppData\Local\Programs\Python\Python35\python35.zip', 8 9 'C:\Users\Administrator\AppData\Local\Programs\Python\Python35\DLLs', 10 11 'C:\Users\Administrator\AppData\Local\Programs\Python\Python35\lib', 12 13 'C:\Users\Administrator\AppData\Local\Programs\Python\Python35', 14 15 'C:\Users\Administrator\AppData\Local\Programs\Python\Python35\lib\site-packages']
如果用sys.path路径表没有你想要的路径,可以通过sys.path.append("路径")添加。
sys.path路径首先是从程序本目录中查找,
注:模块取名字时一定不能与标准库的名字一样
2、第三方模块
下载安装第三方模块有两种方法:
1、是用yum、pip3/pip、apt-get
#requests 发送get请求的 pip3安装 pip3 install requests
2、源码安装
1 # pycrypto,由于 paramiko 模块内部依赖pycrypto,所以先下载安装pycrypto 2 3 # 下载安装 pycrypto 4 wget http://files.cnblogs.com/files/wupeiqi/pycrypto-2.6.1.tar.gz 5 tar -xvf pycrypto-2.6.1.tar.gz 6 cd pycrypto-2.6.1 7 python setup.py build 8 python setup.py install 9 10 # 进入python环境,导入Crypto检查是否安装成功 11 12 # 下载安装 paramiko 13 wget http://files.cnblogs.com/files/wupeiqi/paramiko-1.10.1.tar.gz 14 tar -xvf paramiko-1.10.1.tar.gz 15 cd paramiko-1.10.1 16 python setup.py build 17 python setup.py install 18 19 # 进入python环境,导入paramiko检查是否安装成功
序列化
json和pickle两个模块
json,用于字符串和python基本数据类型间进行转换,可以跨语言!
pickle,用于python所有的类型间转换,但是只能在python语言中用,其它语言解释不了!
Json模块有四个功能:
dumps:没有写入文件,把数据类型转化为所有程序语言都认识的字符串,
dump:把数据类型转化为所有程序语言都认识的字符串,并写入文件
loads:在Python中反序列化,把字符串转化为数据类型,且字符串中的元素要用双引号
load:读取文件中的字符串,并转换python的基础类型
如以下实例:
1 import json 2 li=["name",123,"job"] 3 js=json.dumps(li) 4 print(js,type(js)) 5 #执行结果 6 ["name", 123, "job"] <class 'list'> 7 8 li='["name",123,"job"]' 9 js=json.loads(li) 10 print(js,type(js)) 11 #执行结果 12 ['name', 123, 'job'] <class 'list'> 13 14 li=["name",123,"job"] 15 with open("test","w") as f: 16 json.dump(li,f) 17 #把列表转换为字符,写入同级目录中的test文件中 18 19 with open("test","r") as f: #打开文件,把文件中的内容转换成对应类型 20 li=json.load(f) 21 print(li,type(li)) 22 #执行结果 23 ['name', 123, 'job'] <class 'list'>
pickle也是有四个模块:
dumps、dump、loads、load
给json功能一样,只不过转换过的内容只有python自己能解释:
1 import pickle 2 li=["name",123,"job"] 3 test=pickle.dumps(li) 4 print(test) 5 #执行结果 是python二进制格式 6 b'x80x03]qx00(Xx04x00x00x00nameqx01K{Xx03x00x00x00jobqx02e.' 7 8 9 #转换回来时必须也要是二进制格式 10 test1=pickle.loads(test) 11 print(test1,type(test1)) 12 #执行结果 13 ['name', 123, 'job'] <class 'list'> 14 15 li=["name",123,"job"] #以二进制方式写入文件中 16 with open("db","wb") as f: 17 pickle.dump(li,f) 18 #如字样 �]q (X nameqK{X jobqe. 19 20 21 with open("db","rb") as f: #到文件里取出来 22 li=pickle.load(f) 23 print(li,type(li)) 24 #执行结果 25 ['name', 123, 'job'] <class 'list'>
time模块:
时间模块有三种表示方式:
时间戳: 1970年1月1日之后的秒,可以用time.time()获取
格式化的字符串 2016-06-07 12:12:12, 用tiem.strftime('%Y-%m-%d %H:%M:%S')
结构化时间 元组包括了:年、月、日、星期等 , 用tiem.localtime()
实际运用:
1 import time 2 import datetime 3 4 print(time.time()) #返回当前系统时间戳 如 1465279434.84525 5 6 print(time.ctime()) #返回当前时间 Tue Jun 7 14:03:54 2016 7 8 print(time.ctime(time.time()-86640*2)) #将时间戳转换成时间格式 ,两天前 Sun Jun 5 13:55:54 2016 9 10 print(time.gmtime(time.time()-86640)) #将时间戳转换成struct_time格式格林昨天时间 11 #time.struct_time(tm_year=2016, tm_mon=6, tm_mday=6, tm_hour=5, tm_min=59, tm_sec=54, tm_wday=0, tm_yday=158, tm_isdst=0) 12 13 print(time.localtime(time.time()-86640)) #将时间戳转换成strut_time格式,但返回的是本地昨天时间 14 #time.struct_time(tm_year=2016, tm_mon=6, tm_mday=6, tm_hour=13, tm_min=59, tm_sec=54, tm_wday=0, tm_yday=158, tm_isdst=0) 15 16 print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())) #将结构化的strut_time格式转换为,时间字符传格式 2016-06-07 14:03:54 17 18 print(time.strptime("2016-06-07","%Y-%m-%d"))#与上相反将时间字符串格式,转化为strut_time格式 19 #time.struct_time(tm_year=2016, tm_mon=6, tm_mday=7, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=1, tm_yday=159, tm_isdst=-1) 20 21 22 #datetime 模块 23 print(datetime.date.today()) #输出格式时期格式年月日 2016-06-07 24 print(datetime.date.fromtimestamp(time.time()-86440))#将时间戳格式转化成日期格式 2016-06-06 25 print(datetime.datetime.now()) #显示当前时间详细如:2016-06-07 13:21:12.199884 毫秒都有 26 27 time_s1=datetime.datetime.now() 28 print(time_s1.utctimetuple()) #显示出strut_time格式 29 print(time_s1.replace(2015,5,22)) #显示当前时间,但把日期换成了2015-05-22 30 31 time_s2=datetime.datetime.strptime("21/11/16 17:50","%d/%m/%y %H:%M")#将字符串转换成日期格式 32 new_date=datetime.datetime.now()+datetime.timedelta(days=10)#比现在加10天 2016-06-17 13:57:47.737319 33 new_date1=datetime.datetime.now()+datetime.timedelta(days=-10)#比现在减10天 2016-05-28 13:59:53.181695 34 new_date2=datetime.datetime.now()+datetime.timedelta(hours=-10) #比现在减10小时 2016-06-07 04:01:27.349964 35 new_date3=datetime.datetime.now()+datetime.timedelta(seconds=-10) #比现在减10秒 2016-06-07 14:02:45.919412
logging模块:
Python 使用logging模块记录日志涉及四个主要类,使用官方文档中的概括最为合适:
logger 提供了应用程序可以直接使用的接口;
handler 将(logger创建的)日志记录发送到合适的目的输出;
filter 提供了细度设备来决定输出哪条日志记录;
formatter 决定日志记录的最终输出格式。
Handlers:
handler对象负责发送相关的信息到指定目的地。
Python的日志系统有多种Handler可以使用。有些Handler可以把信息输出到控制台,有些Logger可以把信息输出到文件,还有些 Handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的Handler。可以通过addHandler()方法添加多个多handler
常用的Handlers有两种:
StreamHandler() 显示到屏幕上
FileHandler(filename[,mode]) 写到文件中
filename是文件名,必须指定一个文件名。
mode是文件的打开方式。参见Python内置函数open()的用法。默认是’a',即添加到文件末尾。
Handler.setLevel(lel):指定被处理的信息级别,低于lel级别的信息将被忽略
Handler.setFormatter():给这个handler选择一个格式
Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象
日志模块,分为debug(),info(),warning(),error(),critical()级别;
日志级别大小关系为:CRITICAL > ERROR > WARNING > INFO > DEBUG
默认是从WARNING级别将log 打印到屏幕如:
1 import logging 2 3 logging.debug("hello debug") 4 logging.info("hello info") 5 logging.warning("hello warning") 6 logging.error("hello error") 7 logging.critical("server is down") 8 9 #执行结果 10 WARNING:root:hello warning 11 ERROR:root:hello error 12 CRITICAL:root:server is down
简单用法
1 logging.basicConfig(level=logging.DEBUG, 2 format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s %(name)s ', 3 datefmt='%Y-%m-%d %H:%M:%S', 4 filename='myapp.log', 5 filemode='w') 6 7 logging.debug('This is debug message') 8 logging.info('This is info message') 9 logging.warning('This is warning message') 10 11 #./myapp.log文件里的信息如下 12 2016-06-07 15:11:29 logger.py[line:17] DEBUG This is debug message root 13 2016-06-07 15:11:29 logger.py[line:18] INFO This is info message root 14 2016-06-07 15:11:29 logger.py[line:19] WARNING This is warning message root
logging.basicConfig函数各参数:
filename: 指定日志文件名
filemode: 和open函数意义相同,指定日志文件的打开模式,'w'或'a'
format: 指定输出的格式和内容,format可以输出很多有用信息,如上例所示:
%(levelno)s: 打印日志级别的数值
%(levelname)s: 打印日志级别名称
%(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s: 打印当前执行程序名
%(funcName)s: 打印日志的当前函数
%(lineno)d: 打印日志的当前行号
%(asctime)s: 打印日志的时间
%(thread)d: 打印线程ID
%(threadName)s: 打印线程名称
%(process)d: 打印进程ID
%(message)s: 打印日志信息
datefmt: 指定时间格式,同time.strftime()
level: 设置日志级别,默认为logging.WARNING
把日志同时输出屏幕和文件:
这个很牛逼的,可以限制级别写到屏幕或者文件,以下实例我就是把DEBUG级别以上的写到文件中,把INFO级别以上的直接在屏幕显示:
1 import logging 2 logging.basicConfig(level=logging.DEBUG, 3 format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s %(name)s ', 4 datefmt='%Y-%m-%d %H:%M:%S', 5 filename='myapp.log', 6 filemode='w') 7 8 9 display=logging.StreamHandler() 10 display.setLevel(logging.INFO) #设置级别 11 formater=logging.Formatter("%(name)s %(asctime)s %(levelname)s %(message)s") #格式化定义规则 12 datefmt='%Y-%m-%d %H:%M:%S' #时间格式 13 display.setFormatter(formater) #导入格式化 14 logging.getLogger("").addHandler(display) #返回一个logger对象,如果没有指定名字将返回root logger 15 16 logging.debug('This is debug message') 17 logging.info('This is info message') 18 logging.warning('This is warning message') 19 20 #屏幕上打印 21 root 2016-06-07 15:31:21,137 INFO This is info message 22 root 2016-06-07 15:31:21,137 WARNING This is warning message 23 24 #./myapp.log文件中内容为: 25 2016-06-07 15:31:21 logger.py[line:25] DEBUG This is debug message root 26 2016-06-07 15:31:21 logger.py[line:26] INFO This is info message root 27 2016-06-07 15:31:21 logger.py[line:27] WARNING This is warning message root