python 第五天

双层装饰器
#一个装饰器用另一个装饰器的功能
#一个函数用两个装饰器
#第三

#双层装饰器记法:
    #---解释时从下往上解释
    #---执行时从上到下执行
   
解释顺序:
1.将index函数传给check_admin,生成新的函数(即check_admin的inner),老index函数为check_admin的func
2.将check_admin函数传给check_login,生成新的函数(即check_login的inner),老的check_admin的inner变成了func
   
执行顺序:
1.执行check_login函数,判断成功后执行func即check_admin的inner函数
2.再执行check_admin的inner函数,判断成功后执行执行func即原始index函数

@check_login                                     #第二次装饰,相当于在第一次装饰完成后用新生成的”新的index函数“又被创建了一个”新的index函数“
@check_admin                                     #第一次装饰,相当于创建了一个 "新的index函数",是check_admin的inner函数体
def index():
    print('index')   
   
   
   
   
   
#双层装饰器程序   
#!/usr/bin/env python
#-*- coding:utf-8 -*-
# Author:Minghu Wang

#判断登录
USER_INFO = {}
#USER_INFO['is_login']
#USER_INFO.get('is_login',None)

def check_login(func):
    def inner(*args, **kwargs):
        if USER_INFO.get('is_login',None):       #如果is_login为真时,.get是判断is_login的values值不存在,返回None,即定位默认值
        #.get 如果键值不存在,可定义第二个参数,返回None
            ret = func(*args, **kwargs)              #check_admin生成的”新的index“函数
            return ret
        else:
            print('请登录')                       #没登录返回信息
    return inner


#只判断管理,不判断登录
def check_admin(func):
    def inner(*args, **kwargs):

        if USER_INFO.get('user_type',None) == 2:
            ret = func(*args, **kwargs)          #原index函数
            return ret
        else:
            print('无权限查看')                  #登录后,无权查看选项返回信息

    return inner

#一个函数用两个装饰器,从下到上装饰   
@check_login                                     #第二次装饰,相当于在第一次装饰完成后用新生成的”新的index函数“又被创建了一个”新的index函数“
@check_admin                                     #第一次装饰,相当于创建了一个 "新的index函数",是check_admin的inner函数体
def index():
    print('index')

@check_login
def home():
    print('home')

def login():
    user = input('请输入用户名:')
    if user == 'admin':
        USER_INFO['is_login'] = True
        USER_INFO['user_type'] = 2
    else:
        USER_INFO['is_login'] = True
        USER_INFO['user_type'] = 1

def main():
    while True:
        inp = input('1,登录; 2,查看信息; 3,超级管理员管理 \n >>>')
        if inp == '1':
            login()
        elif inp == '2':
            home()
        elif inp == '3':
            index()
main()

 

 

 

字符串格式化
    两种方法:format 和 %

    % 常用字符串格式化
        tpl = "i am %s" % "alex"
        tpl = "i am %s age %d" % ("alex", 18)
        tpl = "i am %(name)s age %(age)d" % {"name": "alex", "age": 18}         #定义变量,以字典方式格式化
        tpl = "percent %.2f" % 99.97623                                         #取小数点后两位
        tpl = "i am %(pp).2f" % {"pp": 123.425556, }                            #把pp的key值传入,再取小数点后两位
        tpl = "i am %.2f %%" % 123.425556                                       #取小数点后两位,取百分号,%%防转义

 

    format字符常用方法
        tpl = "i am {}, age {}, {}".format("seven", 18, 'alex')                                  #{}为空占位符,随意传,按顺序参数
        tpl = "i am {}, age {}, {}".format(*["seven", 18, 'alex'])                               #给列表加*是分别按顺序给占位符传值,不然会报错
        tpl = "i am {0}, age {1}, really {0}".format("seven", 18)                                #{}占位符中指定索引号是为了传固定的值,不按顺序传,自由度高
        tpl = "i am {0}, age {1}, really {0}".format(*["seven", 18])                             #把列表传给{}占位符索引,用*分别传值
        tpl = "i am {name}, age {age}, really {name}".format(name="seven", age=18)               #{name} 占位符变量名,按变量名传值
        tpl = "i am {name}, age {age}, really {name}".format(**{"name": "seven", "age": 18})     #{name} 占位符变量名,**以字典分别将key的value值传值
        tpl = "i am {0[0]}, age {0[1]}, really {0[2]}".format([1, 2, 3], [11, 22, 33])           #{0[0]}占位符作用是以列表的索引的元素位值传值
        tpl = "i am {:s}, age {:d}, money {:f}".format("seven", 18, 88888.1)                     #{:s}等以固定类型传值,{s:}字符串,{:d}数字,{:f}浮点型
        tpl = "i am {:s}, age {:d}".format(*["seven", 18])                                       # * 星的作用是把列表值分别传给固定的类型
        tpl = "i am {name:s}, age {age:d}".format(name="seven", age=18)                          #{name:s}等是以变量和固定类型限制传的值必须是固定类型
        tpl = "i am {name:s}, age {age:d}".format(**{"name": "seven", "age": 18})                # ** 双星的作用是把字典的value值分别传入
        tpl = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%}".format(15, 15, 15, 15, 15, 15.87623, 2)  #按{:b}二进制,{:o}八进制,{:d}十进制,{:x}十六进制,{:X}大写十六进制,{:%}百分比  传值
        tpl = "numbers: {0:b},{0:o},{0:d},{0:x},{0:X}, {0:%}".format(15)                         #按索引传值,用各种进制和类型转换
        tpl = "numbers: {num:b},{num:o},{num:d},{num:x},{num:X}, {num:%}".format(num=15)         #指定变量num,按变量传值,用各种进制和类型转换

 

#左对齐减号  -10  包含字符长度
s = "asdf%(name)  -10saaa %(age)-10d   %(p).2f" %{'name':'alex','age': -123, "p": 1.236567}
print(s)

#进制转换 %s  %c %x %g
s  = "asdifuyaksdf %c ---- %o  ===== %x ===== %g" %(65, 15, 15, 100)
print(s)
s1 = "alex %"
print(s1)

#当格式化时,字符串中出现占位符 %s.. 需要用 %% 输出 %
s2 = "alex %s %%" %('SB')
print(s2)

#根据索引号传值
s1 = "asdfasdf{0}a123{0}123{1}".format(123, "alex")
print(s1)


#固定类型格式化
s1 = "----{name:s}____{age:d}===={name:s}".format(name='alex', age=123)
print(s1)

#居中格式化
s2 = "----{:*^20s}====={:+d}===== {:x}".format('alex', 123, 15)
print(s2)

#取小数点后两位并带百分比
s3 = "asdfasdfasd {:.2%}".format(0.234567)
print(s3)

 

 

生成器  (yield)
    出现yield 就是生成器
    yield 控制顺序,保存上次执行的位置
    生成器,本质就是yield控制位器,按顺序一个一个执行

程序1
def func():
    print(1111)
    yield 1
    print(222)
    yield 2
    print(333)
    yield 3

ret = func()
r1 = ret.__next__() #进入函数找到yield,获取yield后的数据,__next__ 一个一个拿yielld函数位的值
print(r1)
r2 = ret.__next__() #进入函数找到yield,获取yield后的数据
print(r2)
r3 = ret.__next__() #进入函数找到yield,获取yield后的数据
print(r3)
# r4 = ret.__next__() #进入函数找到yield,获取yield后的数据
# print(r4)

 


#自写range功能1
def myrange(arg):
    start = 0
    while True:
        if start > arg:
            return
        yield  start

        start += 1
ret = myrange(3)
r = ret.__next__()
print(r)
r = ret.__next__()
print(r)
r = ret.__next__()
print(r)
r = ret.__next__()
print(r)

 


#自写range功能2
def myrange(arg):
    start = 0
    while True:
        if start > arg:
            return
        yield  start

        start += 1
ret = myrange(3)            #循环遍历四次(包括0)
for item in ret:
    print(item)
   
   
   
   
   

函数嵌套调用
def d():
    return '123'

def c():
    r = d()              #调用d函数
    return r

def b():
    r = c()                 #调用c函数
    return r

def a():   
    r = b()                 #调用b函数
    print(r)

a()                     #执行a函数,应该一层层找,打印123

 

 

递归函数
def func(n):
    n += 1
    print(n)
    if  n > 4:
        return 'end'
    return func(n)     #这个return为了返回函数结果(end)

r = func(1)
print(r)


模块:
    内置模块
    自定义模块
    第三方模块

    为什么要有模块?
        将代码归类

导入模块的依据
    import sys
    sys.path
   

模块
py:模块
其他:类库
        先导入
        后写入

sys.argv传参模块:

#a.py程序
#!/usr/bin/env python
#-*- coding:utf-8 -*-
# Author:Minghu Wang
import sys
print(sys.argv)

python a.py  jkdsjf jfkdsjf  jksfdjf

 


#函数调用(导入)

#目录结构
day5/
├── lib
│?? ├── commons.py
│?? └── __pycache__
│??     └── commons.cpython-35.pyc
├── __pycache__
│?? └── s4.cpython-35.pyc
├── s3.py                               #执行函数,调用s4.py、lib/commons.py
├── s4.py
└── s4.pyc

 

lib  目录下的
commons.py
    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    # Author:Minghu Wang
    def f1():
        print("F1")

 

s4.py
    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    # Author:Minghu Wang
    def login():
        print("login")
       
    def logout():
        print('logout')

 

 

执行函数
s3.py
    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    # Author:Minghu Wang
    import s4
    import lib.commons

    s4.login()
    lib.commons.f1()

 

结果
    login
    F1


跨目录导模块
    sys.path  #导入模块先到sys.path的目录找
    从上到下找,找不到就报错

 

在opt目创建脚本
vi /opt/outer.py
def aa():
    print('wmh')


在任意目录创建脚本调用
#导入我的模块
vi  /root/a.py
import sys
sys.path.append("/opt")
import outer
outer.aa()


执行a.py
python a.py

返回结果
wmh

 

 

#模块名称非常重要,不要和内置重名
#创建自己的模块不要和内置模块一样,不然只执行自己的,不执行内置的
import sys
print(sys.path)


#执行函数
s3.py
#!/usr/bin/env python
#-*- coding:utf-8 -*-
# Author:Minghu Wang
import lib.commons
from  s4 import login   #从s4.py模块 导入login函数
login()                    #直接执行

s4.login()
lib.commons.f1()

 

调用模块方法
    from s4 import *      #导入s4.py模块所有函数
    from lib import commons  #导入同级lib目录的commons.py模块
    commons.f1()  


#模块别名
from lib  import commons1 as commons1
from lib  import commons as commons2

 

#导入模块
单模块
    使用  import
嵌套文件夹下
    使用    from lib  import commons          #单独导入
            from lib  import commons as f1    #别名

 

 


#安装requests
#加环境变量
C:\Users\Administrator\AppData\Local\Programs\Python\Python35\Scripts  
python3 -m pip install --upgrade pip
python3 -m pip install requests

import requests

 

 

序列化模块
json
    json.dumps  #将pyhton 基本数据类型转成字符串       (序列化)
    json.loads  #将python字符串形式转化成基本数据类型    (反序列化读)
使用方法
    import json          
    import pickle


json使用dumps
    a.py
        import json
        dic = {'k1':'v1'}
        print(dic,type(dic))
        result = json.dumps(dic)    # dumps将pyhton 基本数据类型转成字符串形式
        print(result,type(result)) 

返回结果
{'k1': 'v1'} <class 'dict'>            #原为字典
{"k1": "v1"} <class 'str'>               #dumps转后成为字符串类型


json使用loads
    b.py
        import json
        s1= '{"k1":123}'
       
        dic  = json.loads(s1)         # loads将python字符串形式转化成基本数据类型
        print(dic,type(dic))

返回结果
{'k1': 123} <class 'dict'>

 

 

使用requests抓取页面字符,用json的loads转成字典打印
import json
import requests
response = requests.get('http://wthrcdn.etouch.cn/weather_mini?city=北京')
response.encoding = 'utf-8'
print(response.text)
dic = json.loads(response.text)  #response.text是request的用法,获取http内容
print(dic,type(dic))

 


注意点
import json
r = json.dumps([11,22,33])
li = '["alex","eric"]'    #必须以单引在外,双引在内,不然报错
ret = json.loads(li)         #通过loads反序列化时,一定要用""双引号
print(ret,type(ret))

 


#dump 将列表序列化写到文件
import json
li = [11,22,33]
json.dump(li,open('db','w'))       #将列表序列化写到文件


#load 将文件反序列化读输出
import json
li = json.load(open('db','r'))     #将文件反序列化读输出
print(type(li),li)                 

 

 

json / pickle  区别
    json 更加适合跨语言,字符串基本数据类型
    pickle 所有类型的序列化,仅适用pyhton,可以用于存储加密的程序
    常用为对文件操作

 


pickle 序列化使用

#程序1
import pickle
li = [11,22,33]
r = pickle.dumps(li)    #序列化成python专用类型,你不知道的类型,python专用
print(r)

result = pickle.loads(r)   #将python 类型用loads载入反序列化输出
print(result)

 


#程序2
li = [11,22,33]
pickle.dump(li,open('db','wb'))     #用dump方法以python特定写入到文件

result = pickle.load(open('db','rb'))    #使用load反序列化载入输出
print(result,type(result))

 

 

time 和 datetime 模块使用
import time
import datetime
print(time.time())  #时间戳
print(time.ctime())  #当前时间
print(time.ctime(time.time()-86400))  #昨天
print(time.gmtime())


time_obj = time.gmtime()
print(time_obj)
print(time_obj.tm_year,time_obj.tm_mon)    #取年、月
print(time.localtime())    #本地时间
print(time.mktime(time_obj))   #转成时间戳

 

#睡眠4秒
time.sleep(4)       
print("------")


time.strftime("%Y-%m-%d %H:%M:%S",time.time())
print("-------")
tm = time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime())
print(tm)
tm = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
print(tm)
tm = time.strptime("2016-05-6","%Y-%m-%d")
print(tm)
tm = time.strptime("2016-05-6 15:06","%Y-%m-%d %H:%M")
print(tm)
tm = time.strptime("2016-05-6 15:06","%Y-%m-%d %H:%M")  #字符串转成时间戳
print(time.mktime((tm)))
print(datetime.date.today())
print(datetime.date.fromtimestamp(time.time))

 


#  time和datetime  使用

#_*_coding:utf-8_*_
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 将时间戳转成日期格式


#常用2
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)

时间博客
http://www.cnblogs.com/alex3714/articles/5161349.html

 

 

 

 


时间比较判断
import time
import datetime

#时间比较判断
current_time = datetime.datetime.now()
time_obj = current_time.replace(2015,5)               
print(current_time==time_obj)

 

   
   
   
   
   
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------------------级别----------------------------------
    DEBUG             详细信息,综合诊断                 级别最低
    INFO            工作状态信息
    WARNING            异常警报,突发事件
    ERROR            严重错误,功能失效
    CRITICAL        严重错误,突然中断,不能继续运行
   
   
日志写到文件里   
#level=loggin.INFO 把日志纪录级别设置为INFO,INFO或比INFO级别更高写入文件
#所以 debug信息不写入,因为级别低于info,如果想写,改level=logging.DEBUG即可
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')
       

       
       
       
记录时间日志
import logging
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%Y/%m/%d %I:%M:%S %p')
logging.warning('is when this event was logged.')
       

 

终端和文件同时写需要学习的组件       
    logging库提供了多个组件:Logger、Handler、Filter、Formatter。
        Logger       对象提供应用程序可直接使用的接口,
        Handler      发送日志到适当的目的地,
        Filter          提供了过滤日志信息的方法,
        Formatter   指定日志显示格式。
       


       
       
打印到终端同时写入到文件程序       
#!/usr/bin/env python
#-*- coding:utf-8 -*-
# Author:Minghu Wang


import logging
#创建logger
logger = logging.getLogger('TEST-LOG')           #创建一个logger
logger.setLevel(logging.DEBUG)                     #配置级别
#定义输出到终端
ch = logging.StreamHandler()                       #创建handler,用于输出到终端
ch.setLevel(logging.DEBUG)                         #配置输出终端日志级别
#定义输出到文件
fh = logging.FileHandler("access.log")           #创建一个handler,用于写入日志文件
fh.setLevel(logging.WARNING)                       #配置写入文件日志级别
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')  #定义handler的输出格式formatter

#定义日志输出格式
ch.setFormatter(formatter)                         #以formatter定义的格式输出到终端
fh.setFormatter(formatter)                         #以formatter定义的格式写入到文件
#加载到handler
logger.addHandler(ch)                             #将定义的 ch 日志输出功能添加到handler
logger.addHandler(fh)                             #将定义的 fh 日志输出功能添加到handler

#给日志级别定义内容,并应用
logger.debug('debug message')                  #给日志级别定义内容,并应用
logger.info('info message')
logger.warn('warn message')
logger.error('error message')
logger.critical('critical message')
       
       
       
       
       
结果
2016-06-08 15:54:30,973 - TEST-LOG - DEBUG - debug message
2016-06-08 15:54:30,973 - TEST-LOG - INFO - info message
2016-06-08 15:54:30,973 - TEST-LOG - WARNING - warn message
2016-06-08 15:54:30,974 - TEST-LOG - ERROR - error message
2016-06-08 15:54:30,974 - TEST-LOG - CRITICAL - critical message       

posted @ 2016-06-08 16:24  颠覆自我  阅读(154)  评论(0编辑  收藏  举报