• 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')
  • 相关阅读:
    《那些年啊,那些事——一个程序员的奋斗史》——30
    《那些年啊,那些事——一个程序员的奋斗史》——33
    《那些年啊,那些事——一个程序员的奋斗史》——31
    《那些年啊,那些事——一个程序员的奋斗史》——31
    《那些年啊,那些事——一个程序员的奋斗史》——32
    《那些年啊,那些事——一个程序员的奋斗史》——32
    《那些年啊,那些事——一个程序员的奋斗史》——32
    《那些年啊,那些事——一个程序员的奋斗史》——34
    《那些年啊,那些事——一个程序员的奋斗史》——33
    《那些年啊,那些事——一个程序员的奋斗史》——31
  • 原文地址:https://www.cnblogs.com/mstzkot/p/7200180.html
Copyright © 2020-2023  润新知