python之路:始解

 
 

装饰器

器:表示的是函数 装饰器本质上是函数
装饰器是为了装饰其他函数。就是为其他功能添加附加功能。
装饰器的原则是:1.不能修改被装饰的函数的源代码
        2.不能修改被装饰的函数的调用方式
 
实现装饰器需要明白:
  1、函数即“变量” :函数与变量一样都是存在内存中的,若索引不被删除,则一直在内存中驻留到程序结束。
  2、高阶函数
    1)把一个函数名当做实参传给另外一个函数,在不修改被装饰函数源代码的情况下为其添加功能。
    2)返回值中包含函数名(不修改函数的调用方式)
  3、嵌套函数
 
最终:高阶函数+嵌套函数=装饰器
 
最简单的装饰器如下所示:
部分网站页面在制作完成以后,可能需要经过认证才可以进行下一步的访问,具体实现:
# -*- coding:utf-8 -*-

def login(func):
    def user_pass():
        user=input("请输入用户名:")
        password=input("请输入密码:")
        if user=="miss" and password=="miss":
            res=func()
            return res#结束处需要记得返回当前func运行的结果,否则会将存在return的函数的结果丢失
        else:
            print("输入错误,请重试")
    return user_pass

@login#装饰器语法
def index():
    print("welcome to index")
    return"from home"

@login
def bbs():
    print("welcome to bbs")

def email():
    print("welcome to email")

bbs()

日常的装饰器使用就如展示所示,将login函数冠在要装饰的函数之上,即可完成给函数增加新功能,同时,被装饰函数既感觉不到装饰器的存在,也不会因为被装饰而改变了调用方式。

上面这种是无需往装饰器中传参数的,而另外一种则可能需要往装饰器中传参,比如实现不同页面不同认证方式的效果。

那么我们就可以进行如下所示操作:

# -*- coding:utf-8 -*-

def login(auth_type):#先行传入认证类型
    def outer_wapper(func):
        def user_pass():
            user=input("请输入用户名:")
            password=input("请输入密码:")
            if auth_type=="local":
                if user=="miss" and password=="miss":
                    res=func()
                    return res#结束处需要记得返回当前func运行的结果,否则会将存在return的函数的结果丢失
                else:
                    print("输入错误,请重试")
            elif auth_type=="ldap":
                print("暂无此种认证")
        return user_pass
    return outer_wapper

@login(auth_type="ldap")#加入auth_type以后,整体的传入参数往下压一级
def index():
    print("welcome to index")
    return"from home"

@login(auth_type="local")
def bbs():
    print("welcome to bbs")

def email():
    print("welcome to email")

index()
bbs()

这种方式使用较为普遍。

还有一种方式,是在做作业的时候用到的,就是被装饰函数需要从装饰器中获取自己需要的值,比如还是登录的情况,如果用户登录成功, 那么后续函数会生成一个以当前用户名为文件名的文件,来记录相关信息。而用户登录是在装饰器中完成的,若装饰器无法返回相关相关数据,后续函数则无法完成对应的工作,那么就可以使用如下方式进行提取数据:

# -*- coding:utf-8 -*-


def denglu(func):
    def renzheng(msg):
        user=input("用户名:")
        passwd=input("密码:")
        if user=="admin" and passwd=="123":
            print("认证成功!")
            msg.append(user) #认证成功后,将用户名和密码追加到列表中,通过在return中完成对msg的返回。
            msg.append(passwd)
            return func(msg)
    return renzheng

@denglu
def Main(msg): #函数在收到msg之后,首先对msg进行分离,按照添加的顺序,一一拆分出来。
    user=msg[0]
    passwd=msg[1]
    print("登录成功的用户是%s,密码是%s,创建文件名为%s的文件"%(user,passwd,user))


if __name__ == '__main__':
    msg=[] #此处首先创建一个空列表,方便后续对登录用户名和密码的收集
    Main(msg)

从上面的例子可以看出,我们用了一个列表,按照既定规则追加拆分,即可得到想要得到的数据。此类方法不局限于使用列表,也可以使用字典的形式,如:

msg={}
msg.update("user":user)
msg.update("passwd":passwd)

生成器

在Python中,一边循环一边计算的机制,成为生成器 generator
 
1、只有在调用时才会生成相应的数据
2、只记录当前位置
3、只有一个_next_()方法 在Python2.7里面为next()
 
可以使用如下代码进行生成器的测试。
import time
a=time.time()
s=[i*2 for i in range(0,10000)]
b=time.time()
print(b-a)
#0.0010023117065429688
import time
a=time.time()
s=(i*2 for i in range(0,100000000))
b=time.time()
print(b-a)
#0.0

后者其实并未生成真是的数据,因此速度较快。

由生成器可得生成器函数模型:

# -*- coding:utf-8 -*-


def fib(max):
    n,a,b=0,0,1
    while n<max:
        yield b
        a,b=b,a+b
        n+=1
    return "done"

print(fib(10))
yield 可以实现单线程的情况下并发运算的效果。
yield的效果是保留当前结果并暂停
 
next只是调用yield 不会给yield传值
send是调用yield,同事给yield传值
 
生产者消费者模型:
# -*- coding:utf-8 -*-

import  time
def consumer(name):
    print("%s准备开始吃包子啦"%name)
    while True:
        baozi=yield
        print("包子%s来了,被%s吃掉了"%(baozi,name))


def producer(name):
    c1=consumer("gao")
    c2=consumer("yang")
    c1.__next__() #相当于让consumer成为生成器,启用next之后,就让consumer走到了yield这一步,随后停止
    c2.__next__()
    print("%s开始制作包子"%name)
    for i in range(3):
        time.sleep(1)
        print("做一个包子")
        c1.send(i)
        c2.send(i)

producer("li")

迭代器

可以直接作用于for循环的数据类型:
1、集合数据类型: 如 列表list、元组tuple 、 字典dict、 集合set、 字符串str、 字节类型byte等
2、generator 包括生成器和带yield的generator function
可迭代 即为可循环
可以使用isinstance()判断是否为迭代器对象
 
可以被for循环的对象叫做可迭代对象 iterable可迭代
可以被netxt()函数调用并不断返回下一个值的对象成为可迭代器:iterator。
 
凡是可作用于for循环的对象都是iterable类型
凡是可作用于next()函数的对象都是iterator类型,他们表示一个惰性计算的序列
集合数据类型如list dict str 等是iterable 但不是iterator,不过可以通过iter()函数获得一个iterator对象
Python中的for循环本质上就是通过不断调用next()函数实现的

JSON AND PICKEL

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。json所有语言都通用,可以与不同语言进行数据交互,json默认只是支持最简单的转换类型。与XML相同,但比XML更为简洁方便。
# -*- coding:utf-8 -*-


import json
a={
    1:"2",
    2:"3",
    4:"5"
}



with open("json.txt","w") as f:
    f.write(json.dumps(a))       #########序列化


with open("json.txt","r") as f:
    data=json.loads(f.read())##########反序列化

print(data["1"])

res: 2

pickel

用法跟json类似,但是可以用于python特有的类型 和 python的数据类型间进行转换。
# -*- coding:utf-8 -*-
import pickle
a={
1:"2",
2:"3",
4:"5"
}
 
 
 
with open("pickle.txt","wb") as f:
f.write(pickle.dumps(a))
 
 
with open("pickle.txt","rb") as f:
data=pickle.loads(f.read())
 
print(data[1])

内置模块

1、定义:
模块:用来从逻辑上组织python代码(变量、函数、类、逻辑,从而实现一个功能),本质上就是一个.py结尾的python文件(如文件名为test.py, 则对应的模块名为:test)
python包:本质就是一个文件夹(必须带有一个_init_.py的文件)
 
2.导入方法:
  1、 import module_name
  2、import module_name,module2_name
  3、from module_alex import * 从module_alex 中引用全部的内容,即相当于将module_alex中的内容复制出来了一份
  4、frommodule_alex import 相关函数 可以使用此方式引入想用的函数或者是功能,这样引入的功能直接调用就可以,无需使用原文件名点出来
  5、from module_alex import logger as logger_alex 将logger从module_alex中引入,并将其另外命名为logger_alex
 
 
3、导入模块的本质(路径搜索和搜索路径)
  导入模块的本质就是把python文件解释一遍
  导入包的本质就是执行包下面的_init_.py的文件
  因此可以使用from .import test来进行函数的引用
 
如果要给一个py文件导入模块,那么一定要在sys.path中体现出来,即需要在系统默认的os.path中添加上
os.append()将当前目录追加进去
若想要提高此文件的优先级,可以使用os.insert()来将需要添加的放到前面。
 
4、导入模块的优化,如果一个模块经常性的使用,则可以使用from module import test 将其直接引入,这样可以避免每次都进行查找。
 
 
5、 模块的分类:
  a.标准库
    时间模块:time 和 datetime
        获取时间戳 time.time()
        用来表示时间的方式:1时间戳
                  2格式化的时间字符串
                  3元组(struct_time)
        时间的分类:UTC 格林尼治天文时间,世界标准时间,中国使用的是UTC+8
        DST 夏令时
        time.timezone()显示当前所在时区
        time.altzone()显示夏令时与当前时区的差值
        time.daylight()是否使用了夏令时
        time.sleep()时间停止多长时间,默认时间单位为秒
        time.gmtime()当前时间的格林尼治时间 为UTC时区时间
        time.localtime()当前时间
        以上两种是把时间戳转换为元组的方法
 
        由元组传转换为时间戳:mktime()
 
        由元组转换为字符串:strtime("格式“,元组的时间)
 
        由字符串转化为元组:striptime(”格式化的字符串“,格式)
 
        time.ctime()由时间戳转换为字符串格式 时间戳
 
        time.asctime()由元组转化为字符串格式 参数是元组 tuple
 
        datetime.datetime.now()+datetime..timedelta(3) 当前时间的后三天
 
        datetime.datetime.now()+datetime..timedelta(-3) 当前时间的前三天
  random模块
      random.random()默认随机0到1之间的数值,值类型为浮点数
      random.uniform(1,10) 从一个范围内取值,值类型为浮点数
      random.randint(1,3)随机1-3之间的整数,可以取到3的值
      random.randrange(0,3) 随机1-3之间的整数,不能取到3的值
      random.choice(“”)可以传入字符串、列表、元组等,从中取一个值;随机字符功能
      random.sample(“ hello”,2)从前面的hello中取两个值;随机字符功能,指定取值几
 
  OS模块
      os.getcwd()获取当前的工作目录
      os.chdir(r“c:\”)切换目录
      os.curdir()返回当前目录 类似 Linux下的cd .
      os.pardir()获取当前目录的父目录字符串 类似Linux下的cd ..
      os.makedirs()递归创建目录
      os.removedirs()若目录为空,则删除并递归到上一层,如若也为空,则删除,以此类推
      os.mkdir("dirname") 创建目录 类似Linux下的mkdir test
      os.rmdir() 删除目录,类似linux下的rm -rf
      os.listdir()列出当前目录的文件列表
      os.stat(“test”)获取test的文件信息
      os.sep输出当前平台使用的路径分隔符
      os.linesep输出当前平台使用的行终止符 windows下为“\r\n" Linux下为”\n"
      os.environ列出当前系统的环境变量
      os.pathsep输出用于分割文件路径的字符串
      os.name 获取当前使用平台
      os.system("dir")运行shell命令
      os.path.abspath()获取某一文件的绝对路径
      os.path.split(r"c:\d\e\f")将路径分割成目录和文件名二元组并返回
      os.path.dirname(路径)取此path的路径的值
      os.path.basename(路径) 取此path的文件名的值
      (split、dirname、basename都可以不考虑后面的路径是否存在,其仅仅是处理字符串)
      os.path.exists(r“c:\a”)返回此路径是否存在,存在为True,不存在为False
      os.path.isabbs(路径)判断此路径是否为绝对路径 是为真 否为假
      os.path.join()组合多个路径并返回值,第一个绝对路径之前的参数将被忽略
      os.path.getatime() 返回路径所指向的文件或目录最后的存取时间
      os.path.getmtime()返回路径所指向的文件或目录最后的修改时间
 
  sys模块
      sys.argv()命令行参数list,第一个元素是程序本身路径
      sys.exit()退出程序,正常退出时exit(0)
      sys.version()获取python解释程序的版本信息
      sys.maxint()最大的int值
      sys.path()返回模块的搜索路径,初始化时使用Pythonpath环境变量的值
      sys.platform()返回操作系统平台名称
  shutil模块(copy文件)
      shutil.copyfile(sourceFile,destFile)从源文件拷贝到目标文件
      shutil.copymode(sourceFile,destFile)仅拷贝权限,内容、组、用户均不变
      shutil.copystat(sourceFile,destFile)拷贝状态的信息,不涉及文件内容
      shutil.copy(sourceFile,destFile)拷贝文件和权限
      shutil.cpoy2(sourceFile,destFile)拷贝文件和状态信息
      shutil.copytree(sourceFile,destFile)递归的拷贝文件,即为拷贝文件夹
      shutil.rmtree(sourceFile,destFile)递归的去删除文件,即为删除文件夹
      shutil.make_archive(压缩包的名称,压缩类型,要压缩的路径,用户(默认当前用户),组(默认当前组),记录日志)
      如shutil.make_archive(“test","zip",root_dir="c:\test\"
 
  zipfile模块
    #压缩
      z=zipfile.ZipFile("test.zip","w")将要压缩的文件保存到test.zip中
      z.write()
      z.close()
 
    #解压
      z=zipfile.ZipFile(“test.zip‘,”r“)解压test.zip中的文件
      z.extractall()#可设置解压路径,将压缩包内的文件全部解压
      z.close()
  tarfile模块
     #压缩
      tar=tarfile.open("test.zip","w")
      tar.add()
      tar.close()
 
    #解压
      tar=tarfile.open("test.zip","r")
      tar.extractall()
      tar.close()
  json模块
      json用于字符串和python数据类型间进行交换,可以做到不同语言之间的数据传输
      只支持简单的数据类型
  pickle模块
      用于python特有的类型和Python的数据类型间进行转换
 
  shelve模块
      shelve模块是一个简单的将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的Python数据格式
      例:
      import shelve
      d=shelve.open("test.txt")#打开一个文件
      name=[“rain”,“ass”。“dss”]
      num=[1,2,3,4,5]
      d["name"]=name
      d["num"]=num
      d.close()
 
  xml处理模块
#创建xml文件
import xml.etree.cElementTree as et
new_xml=et.Element("namelist")

name=et.SubElement(new_xml,"name",attrib={"enrolled":"yes"})
age = et.SubElement(name,"age",attrib={"checked":"no"})
sex = et.SubElement(name,"age")
sex.text = '20'
name2 = et.SubElement(new_xml,"name",attrib={"enrolled":"no"})
age = et.SubElement(name2,"age")
age.text = '19'

et = et.ElementTree(new_xml) #生成文档对象
et.write("test.xml", encoding="utf-8",xml_declaration=True
#修改xml文件
import xml.etree.ElementTree as et
 
tree = et.parse("xmltest.xml")
root = tree.getroot()
 
#修改
for node in root.iter('year'):
        new_year = int(node.text) + 1
        node.text = str(new_year)
        node.set("updated","yes")
 
tree.write("xmltest.xml")
 
 
#删除node
for country in root.findall('country'):
      rank = int(country.find('rank').text)
      if rank > 50:
            root.remove(country)
 
tree.write('output.xml')
  hashlib模块
      用于执行加密的相关操作,3.x中代替了md5模块和sha模块,主要是提供SHA1、SHA224、SHA256、SHA256、SHA384、SHA51、MD5算法
      用法:
       
import hashlib
 
s=hashlib.md5()
s.update(b"hello")
print(s.hexdigest())#加密后以十六进制显示
print(s.digest())#加密后以二进制显示
 
  hmac模块:可以创建key和内容,处理以后再进行加密
      hmac 散列消息鉴别码,是一种基于消息鉴别码的鉴别机制,使用HMAC时,消息通讯的双方,通过验证消息中加入的鉴别密钥K来鉴别消息的真伪;一般用于网络通信中消息加密,前提是两者都知道K的值
      用法:
      import hmac
      s=hmac.new(b"youloveit","你好,我是mir赵".encode(encoding="utf-8"))
       print(s.hexdigest())
 
  logging模块
      用于存储各类格式的日志,有5个告警级别:debug(),info(),warning(),error(),critical()
 
      屏幕输出
       
屏幕输出
import logging

logging.debug("this is a debug")
logging.info("this is a info")
logging.warning("this is a warning")#默认从此处开始在屏幕上显示
logging.error("this is a error")

      写入文件

写入文件:(不会在屏幕输出)
import logging

logging.basicConfig(filename="filename.txt",level=logging.DEBUG)
logging.debug("this is a debug")
logging.info("this is a info")
logging.warning("this is a warning")
logging.error("this is a error")
OR


import
logging logging.basicConfig(filename="filename.txt",level=logging.DEBUG,format=("%(asctime)s %(message)s"),datefmt="%Y-%m-%d %H:%M:%S") logging.debug("this is a debug") logging.info("this is a info") logging.warning("this is a warning") logging.error("this is a error") #此处的basicconfig表示的是保存到文件名为filename.txt的文件中,保存等级是从debug开始,格式是“时间 信息” 日期格式为年-月-日 时-分-秒
     
    将日志既要屏幕输出还要存入文件:
#logger提供一个能用程序可以直接时候用的接口
#handle将日志记录发送到合适的目的输出(一个handle就是一个输出地)
#filter提供了细度设备来输出哪条日志记录
#formatter决定日志记录的最终输出格式

#每个程序在输出信息之前都要获得一个logger,即需要为其取一个名称:
import logging
#定义一个logger
Log=logging.getLogger("chat.ui")
Log.setLevel(logging.WARNING)#设置默认级别为warning
#设置格式时间-告警logger名称-告警级别-日志信息
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

#设置两个handle 一个指向屏幕,一个指向文件
screen=logging.StreamHandler()
#屏幕默认级别为错误
screen.setLevel(logging.CRITICAL)
screen.setFormatter(formatter)
#文件默认级别为debug
fileimput=logging.FileHandler("fileinput.txt",mode="a",encoding="utf-8")
fileimput.setLevel(logging.DEBUG)
fileimput.setFormatter(formatter)

Log.addHandler(screen)
Log.addHandler(fileimput)

Log.debug('this is a debug message')
Log.info('this is a info message')
Log.warn('this is a warn message')
Log.error('this is a error message')
Log.critical('this is a critical message')
      按照时间自动截断文件备份      
import logging

from logging import handlers
#设置logger,定义告警级别,设置格式
Log=logging.getLogger("chat.core")
Log.setLevel(logging.DEBUG)
formatter =logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
#屏幕输出
screen =logging.StreamHandler()
screen.setLevel(logging.INFO)
screen.setFormatter(formatter)
#文件输出
#文件名为filetime 时间是按照秒计算,备份数量最多两份,编码类型为utf-8
fileinput =handlers.TimedRotatingFileHandler       \                                    
("filetime",when="S",backupCount=2,encoding="utf-8")

fileinput.setLevel(logging.INFO)
fileinput.setFormatter(formatter)
#将文件输出和屏幕输出添加到Log中,完成接口挂靠
Log.addHandler(screen)
Log.addHandler(fileinput)
#内容
Log.debug('this is a debug message')
Log.info('this is a info message')
Log.warn('this is a warn message')
Log.error('this is a error message')
Log.critical('this is a critical message')
原文地址:https://www.cnblogs.com/mstzkot/p/7200180.html