# 1.内置函数部分
字符串和bytes类型是不可改的数据类型
bytearray 允许在原内存地址修改
chr 对应的ascii二进制数据转成字符和ord()相反
compile() 把一个文件加载进来,按exec或eval的方式解析并执行
exec 可以把字符串编程代码进行执行,注意执行的是代码
a = "print('hello world')"
exec(a)
hello world
eval 可以在字符串中的表达式进行执行,注意执行的是表达式
b = ('1+2+3+4*5')
eval(b)
26
print(exec(b))
None
dir()查看一个对象的方法
filter() 对值完成过滤后进行操作
a = range(0, 10)
b = filter(lambda x: x > 5, a)
for i in b:
print(i)
x相当于函数中的参数,把a中的元素交给lambda
map() 对值本身进行操作
a = map(lambda x: x*x, range(10))
for i in a:
print(i)
a = map(lambda x: x> 1, range(10))
for i in a:
print(i)
globals() 把当前程序中所有的变量显示出来,用来判断一个变量是否存在
locals() 只显示当前程序中的局部变量
hash()把一个字符串变成hash值,只在当前的程序下不会改变
md5() 只要输入不变,输出永远不变,用来做一致性校验
hex() 转成16进制
isinstance() 判断一个对象是否是一个实例
reduce()
from functools import reduce
a = reduce(lambda x,y: x+y , range(10))
print(a)
[0,1,2,3,4,5,6,7,8,9]
1. x = 0, y = 1 x = x + y 即x = 1 , y = 2
2. x = 1, y = 2 x = x + y 即x = 3 , y = 3
可以对列表中的值进行运算,可以+-*/
b = reduce(lambda x, y: x*y, range(1, 10))
print(b)
memoryview 在进行切片和赋值时,不需要copy原列表数据,可以直接映射原数据内存
import time
for n in (100000, 200000, 300000, 400000):
data = b'x'*n
start = time.time()
b = data
while b:
b = b[1:]
print('bytes', n, time.time()-start)
for n in (100000, 200000, 300000, 400000):
data = b'x'*n
start = time.time()
b = memoryview(data)
while b:
b = b[1:]
print('memoryview', n, time.time()-start)
print() 打印进度条
print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
print默认以换行结束输出,并且默认会在缓存中
for i in range(10): print('#', end="") ##########>>> import time for i in range(10): time.sleep(0.5) print('#', end="") ##########>>> 由于print默认flush=false,此时10个#号是先放到缓存,然后整体一下输出 for i in range(10): time.sleep(0.5) print('#', end="", flush=True) ##########>>> 此时将flush=True,就可以看到#号是一个一个的显示打印出来
print file=sys.stdout默认打印到屏幕上,可以指定打印到文件里 f = open('test.txt', 'w') print('hey,you', file=f) f.close()
zip 像衣服的拉链一样,将两边的列表合成1个
a = list(range(10))
b = list(range(10,16))
a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b
[10, 11, 12, 13, 14, 15]
zip(a,b)
<zip object at 0x1088cee48>
list(zip(a,b))
[(0, 10), (1, 11), (2, 12), (3, 13), (4, 14), (5, 15)]
import 时只导字符串形式,有可能要求用户输入,用户输入的时什么模块就导入什么模块
__import__("装饰器")
列表生成式
在讲生成式之前实现[1,2,3,4,5,6,7,8,9]中进行自加1
1. for i in a: b.append(i+1)
2. 拿到下标,自己修改自己
for index,i in enumerate(a):
print(index,i)
a[index] += 1
print(a)
开始使用列表生成式
a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
a = [i + 1 for i in a]
print(a)
[2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [i + 10 if i > 5 else i for i in a]
print(b)
[2, 3, 4, 5, 16, 17, 18, 19, 20]
通过列表生成式引出生成器
收到内存的限制,创建1个包含100万个元素的列表,不仅会占用很多空间,但我们只需要访问前几个元素就不想在循环了,如果用for循环虽然没有用到,但所有的元素已经都在内存中里了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。
在Python中,这种一边循环一边计算的机制,称为生成器:generator。
边运算边执行的计算叫做惰性计算
a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
b = (i + 10 if i > 5 else i for i in a)
print(b)
<generator object <genexpr> at 0x1012f7a40>
查询时只能使用next内置方法一步一步查看
print(next(b))
print(b.__next__())
print(next(b))
print(next(b))
print(next(b))
print(next(b))
print(next(b))
print(next(b))
print(next(b))
1
2
3
4
5
16
17
18
19
全取:for i in b: print(i)
生成器使用
def fib(max): n, a, b = 0, 0, 1 while n < max: # print(b) yield b a, b = b, a+b n = n + 1 return 'done' f = fib(10) print(f.__next__()) print(f.__next__()) print(f.__next__()) print('do someting else') print(f.__next__()) print(f.__next__()) print(f.__next__()) print(f.__next__()) print(f.__next__()) fib(10) 1 1 2 do someting else 3 5 8 13 21
生成器yield保存了函数的中断状态,可以先做些别的事,然后继续。
吃包子程序
知识点:yield可以中断,send既唤醒,又传值
import time def consumer(name): print("%s 准备吃包子啦" %name) while True: baozi = yield # 接收到producer send过来的包子,赋值给包子变量。 print("包子[%s]来了,被[%s]吃了!" % (baozi, name)) def producer(name): c = consumer('A') d = consumer('B') c.__next__() d.__next__() for i in range(10): time.sleep(1) print("做了2个包子") c.send(i) # 调用next并传了一个值给yield d.send(i) producer('庆丰')
迭代器
可以用于for循环的数据类型
一类是集合数据类型
一类是generator
可以直接作用于for循环的对象统称为迭代器Iterable
可以不断的next方法调用的,并不断返回下一个值的对象叫做Iterator
生成器就是迭代器的子集
py3 range() 就是迭代器
py2 range() 是一个列表
模块
时间模块
import time
# 时间戳,从unix诞生之年开始计算1970.1.1开始一共过了多少秒
print('1:', time.time()/60/60/24/365)
# 返回本地时间的时间对象
print('1:', time.localtime())
print('2:', time.localtime(time.time()))
print('3:', time.localtime(time.time() - (60*60*24)))
s_time = time.localtime()
print('4:', s_time.tm_year, s_time.tm_mon, s_time.tm_mday)
# 返回utc林尼治时间的是时间对象
print('1:', time.gmtime())
# 查看和标准格林尼治时间的时差
print('1:', time.altzone/60/60)
# 返回英文格式的日期
print('1:', time.asctime())
print('2:', time.ctime())
# 自定义时间展示格式
print('1:当前时间自定义时间格式字符串-->', time.strftime("%Y-%m-%d %H:%M:%S"))
struct_time = time.localtime(time.time() - 86400)
print('2:自定义1天前时间格式字符串-->', time.strftime("%Y-%m-%d %H:%M:%S", struct_time))
# 字符串转成时间对象
print('1:字符串2017-02-23转成时间对象格式-->', time.strptime("2017-02-23", "%Y-%m-%d"))
# 把时间对象转成时间戳,比两个时间差了多少,需要用时间戳比较
s_time = time.strptime("2017-02-23", "%Y-%m-%d")
print('1:把时间对象转成时间戳-->', time.mktime(s_time))
# 字符串转成时间戳的步骤,1:把字符串转成时间对象 2:把时间对象转成时间戳
print('需要转换的字符串:2017-02-23')
print('1:把字符串转成时间对象得到', time.strptime("2017-02-23", "%Y-%m-%d"))
s_time = time.strptime("2017-02-23", "%Y-%m-%d")
print('2:把时间对象转成时间戳得到', time.mktime(s_time))
# 时间戳转成字符串 1:把时间戳转成时间对象 2:把时间对象转成字符串
print('需要转换的时间戳是:', time.mktime(s_time))
# 1:时间戳转成时间对象
s1_time = time.gmtime(time.mktime(s_time))
print('1: 时间戳转成时间对象得到', s1_time)
# 2:时间对象转成字符串
print('2: 时间对象转成字符串得到', time.strftime("%Y-%m-%d", s1_time))
import datetime
# 用到的方法打印时间,时间计算,时间的替换
print(datetime.datetime.now()) # 返回时间 2017-02-23 19:21:30.235651
print(datetime.date.fromtimestamp(time.time())) # 时间戳直接转成日期格式 2017-02-23
print('当前时间:', datetime.datetime.now())
print('当前时间+3天:', datetime.datetime.now() + datetime.timedelta(3)) # 当前时间+3天
print('当前时间+1小时10分钟:', datetime.datetime.now() + datetime.timedelta(hours=1,minutes=10)) # 当前时间+1小时10分钟
print('当前时间-3天:', datetime.datetime.now() + datetime.timedelta(-3)) # 当前时间-3天
print('当前时间-1小时10分钟:', datetime.datetime.now() + datetime.timedelta(hours=-1,minutes=-10)) # 当前时间-1小时10分钟
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. |
random模块
import random
print(random.randint(1, 10))
print(random.randrange(1, 20, 2))
print(random.sample([1, 2, 3, 4, 5], 2))
# 生成随机验证码
import random
checkcode = ''
for i in range(4):
current = random.randrange(0,4)
if current != i:
temp = chr(random.randint(65,90))
else:
temp = random.randint(0,9)
checkcode += str(temp)
print(checkcode)
import random,string
print(string.ascii_lowercase,string.ascii_uppercase)
source = string.digits + string.ascii_uppercase + string.ascii_lowercase + string.printable
print("".join(random.sample(source, 6)))
os模块
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd
os.curdir 返回当前目录: ('.')
os.pardir 获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2') 可生成多层递归目录
os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() 删除一个文件
os.rename("oldname","newname") 重命名文件/目录
os.stat('path/filename') 获取文件/目录信息
os.sep 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep 输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep 输出用于分割文件路径的字符串
os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command") 运行shell命令,直接显示
os.environ 获取系统环境变量
os.path.abspath(path) 返回path规范化的绝对路径
os.path.split(path) 将path分割成目录和文件名二元组返回
os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) 如果path是绝对路径,返回True
os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间
sys模块
sys.argv 命令行参数List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时exit(0)
sys.version 获取Python解释程序的版本信息
sys.maxint 最大的Int值
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
sys.stdout.write('please:')
val = sys.stdin.readline()[:-1]
pickle模块和json模块
在讲这两个模块之前,需要清楚序列化与反序列化的概念
序列化:内存中的数据 -------> 文件中的字符串
反序列化:文件中的字符串 ------> 内存中的数据
普通方式序列化
# 序列化 account = { "id": 622580102409020, "credit": 15000, "balance": 10000, "expire_date": "2020-5-21", "password": "password" } f = open('account_db', 'w') f.write(str(account)) f.close() # 反序列化 f = open('account_db', 'r') account = eval(f.read()) # eval可以把表达式转成本身的格式 print(account) print(account['id'])
pickle & json
pickle & json 1: 使用方法几乎一样,只是在序列化和反序列化时pickle使用bytes数据类型
json使用的时字符串类型
pickle & json 2: pickle 只是在python内部使用,支持所有python数据类型的序列化与反序列化
json只支持str,int,float,set,dict,list,tuple,但是是通用的序列化格式,可以传给java
使用pickle模块进行序列化与反序列化
# 序列化 import pickle # f.write(pickle.dumps(account)) == pickle.dump(account, f) account = { "id": 622580102409020, "credit": 15000, "balance": 10000, "expire_date": "2020-5-21", "password": "password" } f = open('account_db', 'wb') print(pickle.dumps(account)) # f.write(pickle.dumps(account)) pickle.dump(account, f) # 反序列化 import pickle # pickle.loads(f.read()) == pickle.load(f) # 反序列化,字符串---》内存 f = open('account_db', 'rb') account = pickle.loads(f.read()) # account = pickle.load(f) print(account) print(account['balance']) # 在内存中修改 account['balance'] -= 2000 # 修改后,进行序列化,内存---》字符串 f = open('account_db', 'wb') f.write(pickle.dumps(account)) f.close()
使用json模块进行序列化与反序列化
# 序列化 import json # f.write(json.dumps(account)) == json.dump(account, f) account = { "id": 622580102409020, "credit": 15000, "balance": 10000, "expire_date": "2020-5-21", "password": "password" } f = open('account_db_json', 'w') print(json.dumps(account)) f.write(json.dumps(account)) # json.dump(account, f) # 反序列化 import json # json.loads(f.read()) == json.load(f) # 反序列化,字符串---》内存 f = open('account_db_json', 'r') account = json.loads(f.read()) # account = json.load(f) print(account) print(account['balance']) # 在内存中修改 account['balance'] -= 2000 # 修改后,进行序列化,内存---》字符串 f = open('account_db_json', 'w') f.write(json.dumps(account)) f.close()
login模块
很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误、警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging的日志可以分为 debug()
, info()
, warning()
, error()
and critical() 5个级别,
下面我们看一下怎么用。
最简单用法
1
2
3
4
5
6
7
8
|
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. |
如果想把日志写到文件里,也很简单
1
2
3
4
5
6
|
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就行了。
1
|
logging.basicConfig(filename
=
'example.log'
,level
=
logging.INFO)
|
感觉上面的日志格式忘记加上时间啦,日志不知道时间怎么行呢,下面就来加上!
1
2
3
4
5
6
|
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.
|
日志格式
%(name)s | Logger的名字 |
%(levelno)s | 数字形式的日志级别 |
%(levelname)s | 文本形式的日志级别 |
%(pathname)s | 调用日志输出函数的模块的完整路径名,可能没有 |
%(filename)s | 调用日志输出函数的模块的文件名 |
%(module)s | 调用日志输出函数的模块名 |
%(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 | 用户输出的消息 |
如果想同时把log打印在屏幕和文件日志里,就需要了解一点复杂的知识 了
Python 使用logging模块记录日志涉及四个主要类,使用官方文档中的概括最为合适:
logger提供了应用程序可以直接使用的接口;
handler将(logger创建的)日志记录发送到合适的目的输出;
filter提供了细度设备来决定输出哪条日志记录;
formatter决定日志记录的最终输出格式。
logger
每个程序在输出信息之前都要获得一个Logger。Logger通常对应了程序的模块名,比如聊天工具的图形界面模块可以这样获得它的Logger:
LOG=logging.getLogger(”chat.gui”)
而核心模块可以这样:
LOG=logging.getLogger(”chat.kernel”)
Logger.setLevel(lel):指定最低的日志级别,低于lel的级别将被忽略。debug是最低的内置级别,critical为最高
Logger.addFilter(filt)、Logger.removeFilter(filt):添加或删除指定的filter
Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增加或删除指定的handler
Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():可以设置的日志级别
handler
handler对象负责发送相关的信息到指定目的地。Python的日志系统有多种Handler可以使用。有些Handler可以把信息输出到控制台,有些Logger可以把信息输出到文件,还有些 Handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的Handler。可以通过addHandler()方法添加多个多handler
Handler.setLevel(lel):指定被处理的信息级别,低于lel级别的信息将被忽略
Handler.setFormatter():给这个handler选择一个格式
Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象
每个Logger可以附加多个Handler。接下来我们就来介绍一些常用的Handler:
1) logging.StreamHandler
使用这个Handler可以向类似与sys.stdout或者sys.stderr的任何文件对象(file object)输出信息。它的构造函数是:
StreamHandler([strm])
其中strm参数是一个文件对象。默认是sys.stderr
2) logging.FileHandler
和StreamHandler类似,用于向一个文件输出日志信息。不过FileHandler会帮你打开这个文件。它的构造函数是:
FileHandler(filename[,mode])
filename是文件名,必须指定一个文件名。
mode是文件的打开方式。参见Python内置函数open()的用法。默认是’a',即添加到文件末尾。
3) logging.handlers.RotatingFileHandler
这个Handler类似于上面的FileHandler,但是它可以管理文件大小。当文件达到一定大小之后,它会自动将当前日志文件改名,然后创建 一个新的同名日志文件继续输出。比如日志文件是chat.log。当chat.log达到指定的大小之后,RotatingFileHandler自动把 文件改名为chat.log.1。不过,如果chat.log.1已经存在,会先把chat.log.1重命名为chat.log.2。。。最后重新创建 chat.log,继续输出日志信息。它的构造函数是:
RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])
其中filename和mode两个参数和FileHandler一样。
maxBytes用于指定日志文件的最大文件大小。如果maxBytes为0,意味着日志文件可以无限大,这时上面描述的重命名过程就不会发生。
backupCount用于指定保留的备份文件的个数。比如,如果指定为2,当上面描述的重命名过程发生时,原有的chat.log.2并不会被更名,而是被删除。
4) logging.handlers.TimedRotatingFileHandler
这个Handler和RotatingFileHandler类似,不过,它没有通过判断文件大小来决定何时重新创建日志文件,而是间隔一定时间就 自动创建新的日志文件。重命名的过程与RotatingFileHandler类似,不过新的文件不是附加数字,而是当前时间。它的构造函数是:
TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])
其中filename参数和backupCount参数和RotatingFileHandler具有相同的意义。
interval是时间间隔。
when参数是一个字符串。表示时间间隔的单位,不区分大小写。它有以下取值:
S 秒
M 分
H 小时
D 天
W 每星期(interval==0时代表星期一)
midnight 每天凌晨
import logging
#create logger
logger = logging.getLogger('TEST-LOG')
logger.setLevel(logging.DEBUG)
# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# create file handler and set level to warning
fh = logging.FileHandler("access.log")
fh.setLevel(logging.WARNING)
# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# add formatter to ch and fh
ch.setFormatter(formatter)
fh.setFormatter(formatter)
# add ch and fh to logger
logger.addHandler(ch)
logger.addHandler(fh)
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')