字符串格式化
# 字符串格式化之%占位符 # a. 位置 s = 'i am %s age %d' % ('eason', 18) print(s) ==> i am eason age 18 # 传入可迭代的对象,%占位符会根据迭代传入顺序给字符串赋值 # b. 字典 s = 'i am %(name)s age %(age)d' % {'name':'eason','age':18} print(s) ==> i am eason age 18 # 每一个%占位符会起一个名字,传入一个字典,将字典中%占位符名字的key对应的值传入 # c. 浮点型 s = 'percent %.2f' % 99.97623 # 精确到两位小数点,并四舍五入后一位 print(s) ==> percent 99.98 # d.%显示 # 当格式化字符串时,出现了%s等占位符,需要使用%%才可以输出%(类似于转译) --无占位符时%显示 s = '99%' print(s) --有占位符时%显示 s = 'jack %s 99%%' % 'xx' # 如果使用%需要使用%转译 print(s) ==> 99% jack xx 99% # e. 左右对齐 s = 'xxx|%(name)+10s|xxx' % {'name':'eason'} print(s) s = 'xxx|%(name)-10s|xxx' % {'name':'eason'} print(s) ==> xxx| eason|xxx # 占位10字符,右对齐(+号) xxx|eason |xxx # 占位10字符,左对齐(-号) # f. unicode、8进制、16进制 s = 'unicode:%c oct:%o, hex:%x ' % (65, 15, 15) print(s) ==> unicode:A oct:17, hex:f # 分别将值转为unicode,8进制,16进制
# 字符串格式化之format(字符串方法) # a. format的基本使用 s = 'num1:{0} num2:{0} num{1}'.format(123,456) # 位置可以复用 print(s) ==> num1:123 num2:123 num456 # 注意字符串有三个需要格式化地方,而我们只传入两个,传入索引是可以被复用的 # b. 指定名字修改 s = 'name:{name:s} age:{age}'.format(name='eason', age=12) print(s) # 使用**迭代字典 s = 'name:{name:s} age:{age}'.format(**{'name':'eason', 'age':12}) print(s) ==> name:eason age:12 name:eason age:12 # format不仅支持迭代字典方式,而且支持指定名字修改 # c. 会根据传入类型不同自动去转换 s = 'i am {}, age {}, {}'.format('stenven', 18, 2.3) print(s) ==> i am stenven, age 18, 2.3 # 不需要特定指定字符串类型或者Int或者浮点,传入时自动转换 # d. 传入迭代列表 s = 'i am {}, age {}, {}'.format(*['stenven', 18, 2.3]) # 使用星号遍历字典每一项 print(s) ==> i am stenven, age 18, 2.3 # 迭代列表 # e. 取列表中的元素 s = 'i am {0[0]}, age {1[0]}, {0[2]}'.format(['stenven', 18, 2.3], [18,22]) # 使用星号遍历字典每一项 print(s) ==> i am stenven, age 18, 2.3 # 当我们没有使用"*[列表]"时,列表会当成一个元素传入,而在format格式化中,也可以读取列表某个索引的位置
迭代器
# 概念:迭代器是访问集合元素的一种方式。 # 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。 # 迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退。 # 另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。 # 迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件 特点: 1. 访问者不需要关心迭代器内部的结构,仅需通过next()方法不断去取下一个内容 2. 不能随机访问集合中的某个值 ,只能从头到尾依次访问 3. 访问到一半时不能往回退 4. 便于循环比较大的数据集合,节省内存 # 用我自己简要理解就是: # 1. 迭代器是一个对象 # 2. 该对象不使用__next__方法不返回值
生成器
# 生成器基本概念:用普通的函数语法定义的迭代器 # 取出2层嵌套列表生成器 li = [[1,2],[3,4],[5]] def fla(lis): for sublist in lis: for element in sublist: yield element # 既然生成器本身就是一个迭代器 f = fla(li) r1 = f.__next__() print(r1) r2 = f.__next__() print(r2) r3 = f.__next__() print(r3) r4 = f.__next__() print(r4) r5 = f.__next__() print(r5) ==> 1 2 3 4 5 # 进入函数迭代后,遇到了yield,返回了yield返回值,并在此冻结,在下一次被__next__调用的时候,继续从此开始
递归
# 递归,见递归。这是对“递归”最精简的定义 # 其实按照我的理解就是,在函数中调用自己,就是递归 # 例1:斐波那契递归 def fib(n): if n <= 2: return 1 else: return fib(n-1) + fib(n-2) r = fib(6) # 查看第六位斐波那契序列数字 print(r) # 例2:递归乘法 def f1(n): if n == 1: return 1 return f1(n-1)*n r = f1(5) # 计算从1到5的阶乘 print(r)
JSON序列化
# json序列化 # json序列化4种方法:dumps、dump、loads、load # a. dumps序列化(将Python数据类型转为json格式) import json dic = {'k1':'v1'} print(dic,type(dic)) result = json.dumps(dic) print(result,type(result)) ==> {'k1': 'v1'} <class 'dict'> {"k1": "v1"} <class 'str'> # dumps 将字典序列化为字符串 # b. loads反序列化 dic = json.loads(result) print(dic, type(dic)) ==> {'k1': 'v1'} <class 'dict'> # loads 将字符串反序列化为python字典格式 # 通过json获得天气接口 import requests response = requests.get('http://wthrcdn.etouch.cn/weather_mini?city=北京') response.encoding = 'utf-8' dic = json.loads(response.text) # loads 将字符串反序列化为python字典格式 print(dic) ==> {'data': {'wendu': '30', 'yesterday': {'low': '低温 19.... print(type(dic)) ==> <class 'dict'> # 为字典格式 # dump与load方法同dumps与loads一样, li = [11,22,33] json.dump(li, open('db', 'w')) # 将列表序列化,并写入文件 li =json.load(open('db', 'r')) # 读取文件,并反序列化 print(li) ==> [11, 22, 33] # 注意: # json.loads 或load 反序列化时,由于json对字符串解析原因,请一定要使用单引号括住双引号格式(例: ‘{“k1”:"v1"}’ ),否则json将会反序列化失败报错
pickle序列化
# pickle序列化 # a. 序列化 import pickle li = [11,22,33] r = pickle.dumps(li) # 序列化 print(r) ==> b'\x80\x03]q\x00(K\x0bK\x16K!e.' # 序列后会是一个字节码 # b. 反序列化 result = pickle.loads(r) print(result) ==> [11, 22, 33] # c. 对文件操作的序列化与反序列化 li = [11,22,33] pickle.dump(li, open('db','wb')) # pickle 需使用字节写入 ret = pickle.load(open('db','rb')) # 以字节方式读取 print(ret) ==> [11, 22, 33] # 注意: # 1. pickle序列化为字节码,同样反序列化也是将一个字节码转为本身类型 # 2. pickle与json序列化对比:pickle支持所有Python数据类型,而json仅支持部分Python数据类型,json可夸语言,而pickle仅支持Python,所以各有各的好处与坏处
time模块与datatime模块
# time模块 import time,datetime # a. 时间戳 print(time.time()) # 显示为从1970年1月1日0点开始到现在的秒数(1970年为Unix元年) ==> 1465484260.5525756 # b. ctime方法(获取时间字符串格式) print(time.ctime()) # 系统现在时间的字符串格式 print(time.ctime(time.time()-86640)) # ctime可以传入时间戳参数,例如当前时间戳减去一天秒数 ==> Thu Jun 9 22:57:40 2016 # 现在时间字符串格式 Wed Jun 8 22:53:40 2016 # 减去一天时间字符串格式 # c. gmtime方法(struct_time) print(time.gmtime()) ==> time.struct_time(tm_year=2016, tm_mon=6, tm_mday=9, tm_hour=15, tm_min=0, tm_sec=15, tm_wday=3, tm_yday=161, tm_isdst=0) ### gmtime会返回一个对象,找个对象叫做struct_time time_obj = time.gmtime() print(time_obj.tm_year, time_obj.tm_mon) print("{year}-{mon}".format(year=time_obj.tm_year, mon=time_obj.tm_mon)) ==> 2016 6 # gmtime可以通过以上方式调用使用 2016-6 # 同样我们可以配合使用format,输出自己想要的格式 print(time.gmtime(time.time()-86640)) # 同样gmtime可以传入时间戳参数 # 注意: gmtime默认返回的struct_time是格林威治时间 # d. localtime print(time.localtime(time.time()-86640)) # 将时间戳转换成struct_time,但返回的本地时间 ==> time.struct_time(tm_year=2016, tm_mon=6, tm_mday=8, tm_hour=23, tm_min=21, tm_sec=24, tm_wday=2, tm_yday=160, tm_isdst=0) # 与gmtime一样返回struct_time格式,但是返回本地时间而不是格林威治时间 # e. mktime(将struct_time格式转换为时间戳格式) print(time.mktime(time.localtime())) # 与time.localtime()功能相反,将struct_time格式转回城时间戳格式 ==> 1465485924.0 # f. time.sleep() 程序睡眠 time.sleep(4) # 程序睡眠4s # g. strftime(将struct_time格式转换为指定的字符串格式) print(time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime()) ) ==> 2016-06-09 15:30:32 # 注意gmtime和localtime区别使用 # h. strptime(将字符串格式转换成struct_time格式) print(time.strptime("2016-01-28","%Y-%m-%d") ) ==> time.struct_time(tm_year=2016, tm_mon=1, tm_mday=28, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=28, tm_isdst=-1)
# datetime模块 # a. 输出当天字符串 print(datetime.date.today()) ==> 2016-06-09 # b. 将时间戳转成日期格式 print(datetime.date.fromtimestamp(time.time())) ==> 2016-06-09 # c. 将现在时间转为struct_time格式 current_time = datetime.datetime.now() # print(current_time) #输出2016-01-26 19:04:30.335935 print(current_time.timetuple()) #返回struct_time格式 ==>2016-06-09 23:38:58.100283 time.struct_time(tm_year=2016, tm_mon=6, tm_mday=9, tm_hour=23, tm_min=38, tm_sec=58, tm_wday=3, tm_yday=161, tm_isdst=-1) # d. 使用datetime进行时间的加减 new_date = datetime.datetime.now() + datetime.timedelta(days=10) #比现在加10天 print(new_date) ==> 2016-06-19 23:44:48.365317 new_date = datetime.datetime.now() + datetime.timedelta(days=-10) #比现在减10天 print(new_date) ==> 2016-05-30 23:44:48.365317 new_date = datetime.datetime.now() + datetime.timedelta(hours=-10) #比现在减10小时 print(new_date) ==> 2016-06-09 13:44:48.365317 new_date = datetime.datetime.now() + datetime.timedelta(seconds=120) #比现在+120s print(new_date) ==> 2016-06-09 23:46:48.365317 # e. 修改时间 current_time = datetime.datetime.now() print(current_time.replace(2014,9,12)) # 输出2014-09-12 23:48:52.619287,返回当前时间,但指定的值将被替换 ==> 2014-09-12 23:48:52.619287 # f. 时间前后的比较 current_time = datetime.datetime.now() # 当前时间 current2_time = current_time.replace(2014,9,12) # 替换14年9月份时间 # 首先我们要知道,我们这两个变量并不是字符串格式,而是datetime格式 print(type(current_time)) ==> <class 'datetime.datetime'> print(current_time>current2_time) # ==> True print(current_time# ==> False # 时间格式是可以直接对比比较的
日志模块
# 日志模块 import logging # a. 初识 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 # 直接使用,默认打印到屏幕,并且默认还帮你补充了root用户 # b. 日志级别 DEBUG、INFO、WARNING、ERROR、CRITICAL # 分别对应方法: logging.debug('debug') logging.info('info') logging.warning('warning') logging.error('error') logging.critical('critical') # c. 将日志不输出到屏幕,而是存入log文件 logging.basicConfig(filename='example.log',level=logging.INFO) # 指定log文件名,log级别 logging.debug('This message should go to the log file') logging.info('So should this') logging.warning('And this, too') # example.log == > INFO:root:So should this WARNING:root:And this, too # 因为我们日志级别为INFO,所以并没有将debug日志写入到日志文件 # d. 日志中增加时间 logging.basicConfig(filename='example.log',level=logging.INFO, format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') # 这里format参数中%(asctime)s 表示时间占位符 logging.warning('is when this event was logged.') # example.log ==> 06/10/2016 01:16:49 AM So should this 06/10/2016 01:16:49 AM And this, too
# logging进阶 import logging #create logger # 刚刚我们默认输出日志中增加一个root, getLogger参数指定root那个位置索要显示的用户名也好或者你自定义标记 logger = logging.getLogger('TEST-LOG') # setLevel方法设定一个全局的日志级别 logger.setLevel(logging.DEBUG) # create console handler and set level to debug # 我要输出到哪里,决定权在handler # StreamHandler屏幕输出日志 ch = logging.StreamHandler() # setLevel 设置屏幕输出日志的级别(相对于全局,这就是一个局部日志级别) ch.setLevel(logging.DEBUG) # create file handler and set level to warning # FileHandler文件输出日志 fh = logging.FileHandler("access.log") # 同样,setLevel给我们文件输出日志也定义一个级别 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 # 我们刚刚定义屏幕输出对象(ch)和文件输出对象(fh),相当于注册到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')