python学习笔记-Day5

字符串格式化

# 字符串格式化之%占位符

# 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<current2_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')

 

posted @ 2016-06-09 01:40  Cool_King  阅读(225)  评论(0编辑  收藏  举报