本节内容:1、双层装饰器
2、字符串格式化
3、递归
4、生成器、迭代器
5、模块
双层装饰器
USER_INFO = {} def check_login(func): def inner(*args,**kwargs): if USER_INFO.get(‘is_login‘,None): ret = func(*args,**kwargs) return ret else: print("请登录") return inner def check_admin(func): def inner(*args,**kwargs): if USER_INFO.get(‘user_type‘,None): ret = func(*args,**kwargs) return ret else: print("无权限") return @check_login @check_admin def index(): print("index") index()
#从下晚上渲染(编译解释),@chec_admin装饰index函数,它们作为一个整体,假设这个整体的名字为nindex,那么@chec_login装饰的就是nindex。 #从上往下之行,先之行@chec_login,执行里面的func也就是执行index,index就是@check_admin和index函数,接下来执行check_admin里的func,也就是执行index 函数,那它执行的就是check_admin里的inner 函数.
字符串格式化
Python的字符串格式化有两种方式: 百分号方式、format方式
百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存。
百分号方式
%[(name)][flags][width].[precision]typecode
- (name) 可选,用于选择指定的key
- flags 可选,可供选择的值有:
- + 右对齐;正数前加正好,负数前加负号;
- - 左对齐;正数前无符号,负数前加负号;
- 空格 右对齐;正数前加空格,负数前加负号;
- 0 右对齐;正数前无符号,负数前加负号;用0填充空白处
- width 可选,占有宽度
- .precision 可选,小数点后保留的位数
- typecode 必选
- s,获取传入对象的__str__方法的返回值,并将其格式化到指定位置
- r,获取传入对象的__repr__方法的返回值,并将其格式化到指定位置
- c,整数:将数字转换成其unicode对应的值,10进制范围为 0 <= i <= 1114111(py27则只支持0-255);字符:将字符添加到指定位置
- o,将整数转换成 八 进制表示,并将其格式化到指定位置
- x,将整数转换成十六进制表示,并将其格式化到指定位置
- d,将整数、浮点数转换成 十 进制表示,并将其格式化到指定位置
- e,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(小写e)
- E,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(大写E)
- f, 将整数、浮点数转换成浮点数表示,并将其格式化到指定位置(默认保留小数点后6位)
- F,同上
- g,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是e;)
- G,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是E;)
- %,当字符串中存在格式化标志时,需要用 %%表示一个百分号
注:Python中百分号格式化是不存在自动将整数转换成二进制表示的方式
常用格式化:
tp1 = "i am %s" % "QL" print(tp1) tp2 = "i am %s age %d" % ("QL",18) #顺序添加 print(tp2) tp3 = "i am %(name)s age %(age)d" %{"name":"QL","age":18,} #命名添加 print(tp3) tp4 = "percent %.2f" % 99.98765 print(tp4) tp5 = "i am %(pp).2f %%" %{"pp":123.2312444,} #可以命名也可以不命名 print(tp5) tp6 = "i am %.2f %%" % 123.123123 #显示百分号,需要写两个% 相当于转译 print(tp6) s = "我是%(name)s age %(age)d" % {‘name‘:‘QL‘,‘age‘:21} print(s) #我是QL age 21 s1 = "我是%(name)-10saa %(age) +10daa" %{‘name‘:‘QL‘,‘age‘:12} print(s1) #我是QL aa +12aa s2 = "hello %c------%o=====%x" % (65,15,15) #%c是asc码,%o是8进制,%x16进制 print(s2) #hello A------17=====f
format 方式
[[fill]align][sign][#][0][width][,][.precision][type]
- fill 【可选】空白处填充的字符
- align 【可选】对齐方式(需配合width使用)
- <,内容左对齐
- >,内容右对齐(默认)
- =,内容右对齐,将符号放置在填充字符的左侧,且只对数字类型有效。 即使:符号+填充物+数字
- ^,内容居中
- sign 【可选】有无符号数字
- +,正号加正,负号加负;
- -,正号不变,负号加负;
- 空格 ,正号空格,负号加负;
- # 【可选】对于二进制、八进制、十六进制,如果加上#,会显示 0b/0o/0x,否则不显示
- , 【可选】为数字添加分隔符,如:1,000,000
- width 【可选】格式化位所占宽度
- .precision 【可选】小数位保留精度
- type 【可选】格式化类型
- 传入” 字符串类型 “的参数
- s,格式化字符串类型数据
- 空白,未指定类型,则默认是None,同s
- 传入“ 整数类型 ”的参数
- b,将10进制整数自动转换成2进制表示然后格式化
- c,将10进制整数自动转换为其对应的unicode字符
- d,十进制整数
- o,将10进制整数自动转换成8进制表示然后格式化;
- x,将10进制整数自动转换成16进制表示然后格式化(小写x)
- X,将10进制整数自动转换成16进制表示然后格式化(大写X)
- 传入“ 浮点型或小数类型 ”的参数
- e, 转换为科学计数法(小写e)表示,然后格式化;
- E, 转换为科学计数法(大写E)表示,然后格式化;
- f , 转换为浮点型(默认小数点后保留6位)表示,然后格式化;
- F, 转换为浮点型(默认小数点后保留6位)表示,然后格式化;
- g, 自动在e和f中切换
- G, 自动在E和F中切换
- %,显示百分比(默认显示小数点后6位)
常用格式化
s1 = "----{:9^20s}====={:d}====={:x}".format(‘QL‘,16,15) #x是16进制 print(s1) #----999999999QL999999999=====16=====f s2 = "sddddsssss {:.2%}".format(0.1334234) #把数字自动转换成百分比形式,并且保留2位小数 print(s2) #sddddsssss 13.34% tp1 = "i am {},age {}, {}".format("seven",18,‘QL‘) print(tp1) #i am seven,age 18, QL tp2 = "i am {},age {}, {}".format(*["seven",18,"QL"]) #列表传递前面要加* print(tp2) tp3 = "i am {0},age {1},really {0}".format("seven",18) print(tp3) #i am seven,age 18,really seven tp4 = "i am {name},age{age},really {name}".format(name="seven",age=18) print(tp4) tp5 = "i am {0[0]}, age {0[1]}, really {0[2]}".format([1, 2, 3], [11, 22, 33]) #元素传递 print(tp5) tp6 = "i am {:s}, age {:d}, money {:f}".format("seven", 18, 88888.1) tp7 = "i am {:s}, age {:d}".format(*["seven", 18]) tp8 = "i am {name:s}, age {age:d}".format(name="seven", age=18) tp9 = "i am {name:s}, age {age:d}".format(**{"name": "seven", "age": 18}) tp10 = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2) tpl1 = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2) tpl2 = "numbers: {0:b},{0:o},{0:d},{0:x},{0:X}, {0:%}".format(15) tpl3 = "numbers: {num:b},{num:o},{num:d},{num:x},{num:X}, {num:%}".format(num=15)
递归
#无返回值,None def d(): return‘123‘ def c(): r = d() return r def b(): r =c() return r def a(): r =b() print(r) a() def func(n): n +=1 if n >=4: return "end" return func(n) r = func(1) print(r)
#思考题:1*2*3*4*5*6
迭代器
迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退。另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件
特点:
- 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容
- 不能随机访问集合中的某个值 ,只能从头到尾依次访问
- 访问到一半时不能往回退
- 便于循环比较大的数据集合,节省内存
>>> a = iter([1,2,3,4,5]) >>> a <list_iterator object at 0x101402630> >>> a.__next__() 1 >>> a.__next__() 2 >>> a.__next__() 3 >>> a.__next__() 4 >>> a.__next__() 5 >>> a.__next__()
生成器
一个函数调用时返回一个迭代器,那这个函数就叫做生成器(generator);如果函数中包含yield语法,那这个函数就会变成生成器;
def func(): print("aaaa") yield 1 yield 2 print("ccc") yield 3
上述代码中:func是函数称为生成器,当执行此函数func()时会得到一个迭代器。
ret = func() r1 = ret.__next__() print(r1) r2 = ret.__next__() print(r2) r3 = ret.__next__() print(r3) #结果 aaaa 1 2 ccc 3
实例:
用生成器自定义range
def myrange(arg): start = 0 while True: if start > arg: return yield start start += 1 ret = myrange(5) r = ret.__next__() print(r) r1 = ret.__next__() print(r1) r2 = ret.__next__() print(r2) #结果 0 1 2
模块
模块 (在其他语言里叫类库)
分为三类:
1、开发者写的模块
2、第三方模块
3、自定义模块
为什么要有模块?
将代码归类
先导入,后使用(.py,或者是一个文件夹包含很多.py)
import s1 #一个.py import lib.commons #一个文件夹包含多个.py #调用 f2是s1.py里的函数,f1是lib下的commons.py里的函数 s1.f2() lib.commons.f1()
from s1 import * from s1 import f2 #s1模块名,f2是s1里的函数 f2() from lib import commons from src import commons as src_commons #如果两个文件夹里有相同模块名自可以定义别名 commons.f1()
#模块名字非常重要********* #创建模块名不要和内置模块名一样,先寻找当前目录,找到就不再往下找了,就不会调用内置模块了
查找python 路径
import sys for item in sys.path: print(item) #查找结果,我所使用的是pycharm,并建立了一个s13的项目文件,下面建立了一个day5文件夹,程序就放在这里面 C:\Users\qinling\PycharmProjects\s13\day5 C:\Users\qinling\PycharmProjects\s13 #先在当前目录找模块 在pycharm下会导入项目目录,但在Linux下是不会导入的,所以忽略此目录 C:\Users\qinling\AppData\Local\Programs\Python\Python35\python35.zip C:\Users\qinling\AppData\Local\Programs\Python\Python35\DLLs C:\Users\qinling\AppData\Local\Programs\Python\Python35\lib C:\Users\qinling\AppData\Local\Programs\Python\Python35 C:\Users\qinling\AppData\Local\Programs\Python\Python35\lib\site-packages #第三方模块存放位置 sys.path.append(‘E:\\‘) #导入E盘位置,sys.path是列表,添加python路径
推荐使用导入方法:
单模块: import 嵌套在文件夹下: from xxx import xxx from xxx import xxx as xxxxx
安装第三方模块
1、pip 安装(pip3,python3有,python2,没有)
2、源码安装:
解压进入目录
执行 python3 setup.py install
例如安装requests模块:
pip3 install requests #找到requests模块文件位置 用这个命令安装 python -m pip install requests #不用找到模块文件位置用这个命令就可以安装了
两个序列化相关的模块(把python的字典、列表等转换成字符串)
json
Json模块提供了四个功能:dumps、dump、loads、load
import json dic = {‘k1‘:‘v1‘} print(dic,type(dic)) #{‘k1‘: ‘v1‘} <class ‘dict‘> r = json.dumps(dic) #python基本数据类型转换成字符串形式 print(r,type(r)) #{"k1": "v1"} <class ‘str‘> s1 = ‘{"k1":"123"}‘ #里面必须是双引号,外面必须是单引号 (其他语言单引号叫字符,双引号叫字符串) r1 = json.loads(s1) #将python字符串类型转换成基本数据类型 print(r1,type(r1)) #{‘k1‘: ‘123‘} <class ‘dict‘> li = [11,22,33,] json.dump(li,open(‘db‘,‘w‘)) #先序列化再写入db文件 li = json.load(open(‘db‘,‘r‘)) #先读文件再序列化出来 print(type(li),li) #<class ‘list‘> [11, 22, 33]
使用json做请求获得字符串转化成字典
import json import requests response = requests.get(‘http://wthrcdn.etouch.cn/weather_mini?city=北京‘) response.encoding = ‘utf-8‘ dic1 = json.loads(response.text) print(dic1)
pickle
只能python使用
pickle模块提供了四个功能:dumps、dump、loads、load
li = [11,222,33,] r = pickle.dumps(li) print(type(r),r) #<class ‘bytes‘> b‘\x80\x03]q\x00(K\x0bK\xdeK!e.‘ result = pickle.loads(r) #转化成列表 print(result) #[11, 222, 33] pickle.dump(li,open(‘123‘,‘wb‘)) #先序列化再写入文件 re = pickle.load(open(‘123‘,‘rb‘)) #读文件,序列化后输出 print(re) #[11, 222, 33]
两者区别与优缺点:
json 只能处理基本的数据类型,更加适合跨语言,字符串,如果是一个自己的写的类就不能转换
pickel 支持任何类型,适合对python的所有类型操作,仅适用于python,python版本不同可能会出现问题
time 模块 (http://www.cnblogs.com/alex3714/articles/5161349.html)
常用
import time print(time.time()) #1970年开始计时到现在的系统时间戳 #1465123123.342 print(time.ctime()) #当前时间 #Sun Jun 5 18:38:43 2016 print(time.ctime(time.time()-86400)) #Sat Jun 4 18:38:43 2016 print(time.gmtime()) #time.struct_time(tm_year=2016, tm_mon=6, tm_mday=5, tm_hour=10, tm_min=38, tm_sec=43, tm_wday=6, tm_yday=157, tm_isdst=0) t_obj = time.gmtime() print(t_obj.tm_year,t_obj.tm_mon,t_obj.tm_mday) #2016 6 5 print(time.localtime()) #获取本地时间,本地用哪个时区就获取哪个时区的 #time.struct_time(tm_year=2016, tm_mon=6, tm_mday=5, tm_hour=18, tm_min=40, tm_sec=41, tm_wday=6, tm_yday=157, tm_isdst=0) print(time.mktime(t_obj)) #把时间对象转成时间戳 #1465094462.0 time.sleep(4) print("-------") tm = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()) #常用 将字符串格式转成格式化形式 print(tm) #2016-06-05 18:41:27 tm1 = time.strptime("2016-05-6 15:06","%Y-%m-%d %H:%M") print(tm1) #time.struct_time(tm_year=2016, tm_mon=5, tm_mday=6, tm_hour=15, tm_min=6, tm_sec=0, tm_wday=4, tm_yday=127, tm_isdst=-1)
datetime
常用
import datetime print(datetime.date.today()) #2016-06-05 tm2 = datetime.datetime.now() # 现在的时间 print(tm2) #2016-06-05 18:42:58.458000 print(datetime.datetime.now() + datetime.timedelta(days=10)) #比现在加10天 #2016-06-15 18:42:58.458000 current_time = datetime.datetime.now() print(current_time.replace(2015,5)) #直接回到某个时间 #2015-05-05 18:42:58.458000 time_obj = current_time.replace(2015,5) print(current_time==time_obj)
time &datetime
import time import datetime print(time.clock()) #返回处理器时间,3.3开始已废弃 print(time.process_time()) #返回处理器时间,3.3开始已废弃 print(time.time()) #返回当前系统时间戳 print(time.ctime()) #输出Tue Jan 26 18:23:48 2016 ,当前系统时间 print(time.ctime(time.time()-86640)) #将时间戳转为字符串格式 print(time.gmtime(time.time()-86640)) #将时间戳转换成struct_time格式 print(time.localtime(time.time()-86640)) #将时间戳转换成struct_time格式,但返回 的本地时间 print(time.mktime(time.localtime())) #与time.localtime()功能相反,将struct_time格式转回成时间戳格式 #time.sleep(4) #sleep print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) ) #将struct_time格式转成指定的字符串格式 print(time.strptime("2016-01-28","%Y-%m-%d") ) #将字符串格式转换成struct_time格式 #datetime module print(datetime.date.today()) #输出格式 2016-01-26 print(datetime.date.fromtimestamp(time.time()-864400) ) #2016-01-16 将时间戳转成日期格式 current_time = datetime.datetime.now() # print(current_time) #输出2016-01-26 19:04:30.335935 print(current_time.timetuple()) #返回struct_time格式 #datetime.replace([year[, month[, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]]]]) print(current_time.replace(2014,9,12)) #输出2014-09-12 19:06:24.074900,返回当前时间,但指定的值将被替换 str_to_date = datetime.datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M") #将字符串转换成日期格式 new_date = datetime.datetime.now() + datetime.timedelta(days=10) #比现在加10天 new_date = datetime.datetime.now() + datetime.timedelta(days=-10) #比现在减10天 new_date = datetime.datetime.now() + datetime.timedelta(hours=-10) #比现在减10小时 new_date = datetime.datetime.now() + datetime.timedelta(seconds=120) #比现在+120s print(new_date)
Directive | Meaning | Notes |
---|---|---|
%a |
Locale’s abbreviated weekday name. | |
%A |
Locale’s full weekday name. | |
%b |
Locale’s abbreviated month name. | |
%B |
Locale’s full month name. | |
%c |
Locale’s appropriate date and time representation. | |
%d |
Day of the month as a decimal number [01,31]. | |
%H |
Hour (24-hour clock) as a decimal number [00,23]. | |
%I |
Hour (12-hour clock) as a decimal number [01,12]. | |
%j |
Day of the year as a decimal number [001,366]. | |
%m |
Month as a decimal number [01,12]. | |
%M |
Minute as a decimal number [00,59]. | |
%p |
Locale’s equivalent of either AM or PM. | (1) |
%S |
Second as a decimal number [00,61]. | (2) |
%U |
Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0. | (3) |
%w |
Weekday as a decimal number [0(Sunday),6]. | |
%W |
Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0. | (3) |
%x |
Locale’s appropriate date representation. | |
%X |
Locale’s appropriate time representation. | |
%y |
Year without century as a decimal number [00,99]. | |
%Y |
Year with century as a decimal number. | |
%z |
Time zone offset indicating a positive or negative time difference from UTC/GMT of the form +HHMM or -HHMM, where H represents decimal hour digits and M represents decimal minute digits [-23:59, +23:59]. | |
%Z |
Time zone name (no characters if no time zone exists). | |
%% |
A literal ‘%‘ character. |
logging模块
python的logging模块提供了标准的日志接口,通过它存储各种格式的日志,logging的日志可以分为 debug()
, info()
, warning()
, error()
and critical() 5个级别
import logging logging.warning("user [alex] attempted wrong password more than 3 times") logging.critical("server is down") #输出 WARNING:root:user [alex] attempted wrong password more than 3 times CRITICAL:root:server is down
看一下这几个日志级别分别代表什么意思
Level | When it’s used |
---|---|
DEBUG |
Detailed information, typically of interest only when diagnosing problems. |
INFO |
Confirmation that things are working as expected. |
WARNING |
An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected. |
ERROR |
Due to a more serious problem, the software has not been able to perform some function. |
CRITICAL |
A serious error, indicating that the program itself may be unable to continue running. |
把日志写到文件里
import logging logging.basicConfig(filename=‘example.log‘,level=logging.INFO) logging.debug(‘This message should go to the log file‘) logging.info(‘So should this‘) logging.warning(‘And this, too‘)
其中level=loggin.INFO意思是,把日志纪录级别设置为INFO,只有日志是INFO或比INFO级别更高的日志才会被纪录到文件里,在这个例子, 第一条日志是不会被纪录的,如果希望记录debug的日志,那把日志级别改成DEBUG就行了。
给日志加上时间
import logging logging.basicConfig(format=‘%(asctime)s %(message)s‘, datefmt=‘%m/%d/%Y %I:%M:%S %p‘) logging.warning(‘is when this event was logged.‘) #输出 12/12/2010 11:46:36 AM is when this event was logged.
同时把log打印在屏幕和文件日志里