• PYTHON自动化Day9-发邮件、面向对象、类、私有、继承


    一.发送邮件

    首先我们需要打开邮箱,打开smtp服务,配置客户端授权密码:

     例如:163邮箱

    设置授权码,记住这个授权码,我们需要在发送邮件时使用:

    在本地安装yagmail模块

    python发送邮件代码:

    #以前用 smtplib模块发邮件,但是很麻烦,现在我们用yagmail
    
    import yagmail
    
    username='lilyxxx@163.com'
    passwd = 'xxxxxx'  #授权码
    mail=yagmail.SMTP(user=username,
                      password=passwd,
                      host='smtp.163.com',
                      # smtp_ssl=True,
                      # port=465,  #可以不写port,默认465
                      )  #如果使用的是qq邮箱(因为使用了安全协议),需要加 smtp_ssl=True
    
    mail.send(
        to=['xxxxx@qq.com','xxxxxx@qq.com'],  #如果是单个收件人,直接写string即可,如果是多个写成list
        cc='xxx@xxx.com', #抄送
        subject='测试邮件',  #title
        contents='测试邮件内容',  #内容
        attachments=[r'D:xx自动化须知.txt']  #附件,多个用逗号隔开,放在list里
        )

     PS:如果报错554,说明被认为成了广告或者垃圾邮件

    二.面向对象编程

    1.类

    class Person:  #经典类,类名首字母要大写
        def __init__(self,name): #构造函数  #在实例化这个类时会执行的初始化函数
            # self.name='zl'  #这样就把名字写死了,不好,所以,可以构造函数传入一个参数,作为name
            self.name=name
            self.nose=2  #鼻子   #类里面的变量,叫做属性
            self.face=2 #
            self.head=10 #脑子
            self.wing=4  #翅膀
            print('开始造人。。。')
    
        def driver(self):    #其他函数
            print('%s老司机开车非常稳!' %self.name)  # self的作用,在类中其他方法中可以直接使用self中的内容
            self.eat()  #self可以用来在函数里调用类里面的其他函数
    
        def fly(self):
            print('会飞')
    
        def eat(self):
            print('%s吃火锅' %self.name)
    
    
    #类在使用的时候,首先必须要实例化
    
    zlg=Person('zl')     #实例化,类名加上括号就是实例化, 在实例化时传入name参数,self不算参数,是类中的固定写法
    # zlg=Person(name='zl')  #过个参数的传参方法
    
    zlg.eat()  #引用类中的函数
    zlg.driver()
    zlg.fly()
    print(zlg.name)   #引用类中的变量
    print(zlg.face)
    print(zlg.nose)
    
    
    class Person2(object): #新式类
        pass
    
    #类名首字母大写
    #在python3中经典类和新式类没有区别

    一个练习: 

    需求:

    1、得到一个请求数据:

    vendorId=1697&posCode=pos006&ip=127.0.0.1&posVersion=2.1.1.1.1&mac=;D4-81-D7-CA-20-29;7C-67-A2-9A-06-05;7C-67-A2-9A-06-06;7C-67-A2-9A-06-09;00-00-00-00-00-0000E0
    2、提取到商家编码 vendorId=1697
    3、将商家编码进程2次md5 得到astr
    4、再将请求数据进行一次urldecode得到url_str
    5、astr+url_str 进行一次MD5

    什么是url编码,解码:

    python基础教程     ---->    %DFS%DFDFGD4RG3FD       url编码
    %DFS%DFDFGD4RG3FD    <----     python基础教程       url解码

    url编码加密和解密方法:

    from urllib import parse  #用来url编码,解码
    
    #例如:
    url='http://www.baidu.com?query=python基础教程'
    print(parse.quote_plus(url))  #url编码 加密
    
    url2='http%3A%2F%2Fwww.baidu.com%3Fquery%3Dpython%E5%9F%BA%E7%A1%80%E6%95%99%E7%A8%8B'
    print(parse.unquote_plus(url2))  #url解码,解密

    先用我们之前的定义普通函数的写法:

    
    
    from urllib import parse  #用来url编码,解码
    #下面的方法是原始的函数写作方法,之后我们用类来写,更简洁
    
    import hashlib  #md5需要用的模块
    
    def my_md5(s):
        md=hashlib.md5()
        md.update(s.encode()) #需要先转换成byte格式然后再进行加密
        return md.hexdigest()   #返回加密结果
    
    def get_vendorid(req_data):
        data_dict={}
        # sub_list=req_data.split('&')[0].split('=')[1]  #因为传入的字符串可能是无序的所以这种直接分割的方式不准确,所以我们循环get key和value,写入字典,然后通过key=vendorId来取得 vendorId
        sub_list = req_data.split('&') #先把字符串按照&分割为一个list
        #[vendorId=1697,posCode=pos006,ip=127.0.0.1....]
    
        for i in sub_list:
            k,v=i.split('=')  #vendorId=1697 按照=号把list中的元素再分割为list,分别赋给key和value
            #[vendorId,1697]
            # data_dict.setdefault(k,v)  #存在不覆盖
            data_dict[k]=v   #得到key和value后,写入一个新定义的字典
        # print(data_dict)
    
        return  data_dict.get('vendorId')  #根据vendorId这个key得到我们需要的值return
    
    def sign(req_data):
        verid=get_vendorid(req_data)  #调用函数得到vendorid
        first=my_md5(verid)
        astr=my_md5(first) #按照需求两次加密verid
        url_str=parse.quote_plus(req_data)   #把整个string 进行url编码
        res=my_md5(astr+url_str)  #两个字符串相加再进行一次md5加密
        return res
    
    s='vendorId=1697&posCode=pos006&ip=127.0.0.1&posVersion=2.1.1.1.1&mac=;D4-81-D7-CA-20-29;7C-67-A2-9A-06-05;7C-67-A2-9A-06-06;7C-67-A2-9A-06-09;00-00-00-00-00-0000E0'
    
    print(sign(s))   #调用函数得到加密结果

    下面用类来写:

    #下面用类的方式写:
    
    from urllib import parse
    import hashlib
    
    class Sign(object):
        def __init__(self,req_data):
            self.req_data=req_data   #这写了self,在其他的函数里可以使用self
            self.get_verid()
            self.get_sign()
    
        def md5(self,s):
            md = hashlib.md5()
            md.update(s.encode())
            return md.hexdigest()
    
        def get_verid(self):
            data_dict={}
            sub_list=self.req_data.split('&')
            for i in sub_list:
                k,v=i.split('=')
                data_dict[k]=v
            self.verid=data_dict.get('vendorId')   #这写了self,在其他的函数里可以使用self.verid来使用
    
        def get_sign(self):
            # self.get_verid()  #或者把这句放在__init__里面,总之需要互相调用
            first=self.md5(self.verid)
            astr=self.md5(first)
            url_str=parse.quote_plus(self.req_data)
            self.sign=self.md5(astr+url_str)
            # return self.sign    #不return,也是一样的,因为定义了self.sign, 所以可以直接使用abc.sign来得到sign
    
    
        abc=Sign(s)  #实例化
        print(abc.sign)  #打印出结果,因为函数中定义了变量self.sign来保存结果,所以可以直接通过对象来引用这个变量

    2.下面来看一下if __name__=='__main__': 的作用是什么:

    if __name__=='__main__': 
           pass                 #这句话一般是调试的时候用,
                                #1.如果是直接运行这个python文件,这句话没有作用
                                #2.在别的文件中import这个文件时,就有作用了,如果有这句话,不执行他下面的代码,如果不写这句话,会执行
                                #这句话的意思,就是判断使用的时候是不是本文件在使用,否则表示是外部文件在引用,引用就不执行下面的代码
    print(__name__)  #如果自己这个文件运行时是__main__ , 如果别的文件引用时,是这个文件的文件名 可以在本文件和引用本文件时打印这个变量试试看

    3.析构函数

     前面我们介绍了构造函数,是在实例化的时候会执行的函数,那么在对象不再使用即将销毁之前,能不能做一些操作呢,python也提供了函数,叫做析构函数

    举例:一个优化过的mysql类

    #一个优化过的mysql类:
    
    import pymysql
    class MyDb(object):
        def __del__(self):  #析构函数  会在脚本运行完,也就是实例化的对象不再使用被释放时执行这个析构函数,这里不写释放mysql连接,也会在一定时间自动释放,数据库有配置连接多久后断开,这里只是举例析构函数可以怎么用,用在哪里
            self.cur.close()
            self.conn.close()
            print('over....')
    
        def __init__(self,host,user,passwd,db,port=3306,charset='utf8'):
            try:
                self.conn=pymysql.connect(
                    host=host,user=user,passwd=passwd,port=port,charset=charset,db=db,
                    autocommit=True,#自动提交,不需要commit操作
                )
            except Exception as e:
                print('数据库连接失败!%s' %e)
            else:
                self.cur=self.conn.cursor(cursor=pymysql.cursors.DictCursor)  #返回字典类型
    
        def exsql(self,sql):
            try:
                self.cur.execute(sql)
            except Exception as e:
                print('sql语句有问题,%s' %e)
            else:
                self.res=self.cur.fetchall()
                return self.res
    
    my= MyDb('118.24.3.40','jxz','123456','jxz')
    my.exsql('select * from stu;')

    4.类中的各种特殊的方法类型:

    class Baby():
        country='china' #类变量,公共的变量,每个实例都可以用
        
        def __init__(self,name):  #构造函数
            # print('self的内存地址:',id(self))  #self和实例化后的对象的内存地址是相同的
            self.name=name
            self.money=5000
    
        @property         #定义一个属性方法
        def hhh(self):
            return 198
    
        @classmethod      #定义一个类方法,不需要实例化就可以调用, 可以通过cls来使用类变量,但是不能调用这个类里面的其他实例方法、实例变量,因为他只能通过cls来调用其他,而不是self
        def xm(cls):        #在不想实例化的时候,就可以定义成类方法
            print(cls.country)
            print('我是类方法')
    
        @staticmethod   #静态方法
        def xh():
            print('这是个静态方法,他和一个没写在类里面的函数一样')    #不能使用类变量,类方法,实例变量,实例方法
    
    Baby.country='usa' #类变量可以直接通过类名.xxx来修改的
    Baby.xm()  #类方法在不实例化也可以调用,和实例化后调用相同
    
    abc=Baby('lily')
    abc.xm()
    print('实例化1的内存地址',id(abc))
    print(abc.hhh)
    print(abc.hhh()) #如果没有加@property,需要这样调用
    
    print(abc.name)
    print(abc.money)
    abc.car='bmw'   #给对象添加一个类属性
    print(id(abc.car))
    
    #self 代表的是本类对象, 就是实例化之后的对象, 所以class里的内容加上self,那么在这个类里面就都可以调用了,因为self表示的是同一块内存地址

    5.继承:

    class Lz(object):   #父类
        def __init__(self):
            self.money=1000000000
            self.house='三环20套'
    
        def sing(self):
            print('唱歌')
    
        def dance(self):
            print('跳舞')
    
        def friend(self):
            print('朋友')
    
    
    class Xz(Lz):   #继承Lz的内容,子类
        def dance(self):   #如果定义了和父类相同的方法,就在子类里重写了这个方法
            print('交谊舞')
        pass
    
    a=Xz()
    a.dance()
    print(a.money)
    
    #用法:
    #例如,可以这样定义函数的公共部分
    class Base(object):
        def __init__(self,host,port,password):
            self.host=host,
            self.port=port,
            self.password=password
    
    class Mysql(Base):  #减少代码重复
        pass
    class Redis(Base):
        pass

    6.私有:

    例子:优化一个redis的类:(待完成)

    import redis
    class My(object):
        def __init__(self):
            self.__host='118.24.3.40'        #self.host在前面加__,就定义成了私有变量,只能在类里面使用,外部不能调用, 同理在方法名前面加__,就定义成了私有方法,外部不能调用
            self.__port=6379
            self.__password='HK139bc&*'
            self.r=redis.Redis(host=self.host,port=self.port,password=self.password)
        def get(self,k):   #根据key查询string类型的valuereturn None
        def str_set(self,k,v):   #新增一个string类型的keypass
        def str_del(self):  #删除stringl类型的key
            pass
        def hash_get(self):
            pass
        def hash_set(self):
            pass
        def hash_getall(self):
            pass
        def hash_del(self):
            pass
    
    my=My()
    my.port=9999   #如果可以随意修改很容易出错,所以我们可以把它设置为私有的 self.__port=6379
    print(my.__port)   #不能调用

    已经完成优化的redis类:

    import redis
    
    # r = redis.Redis()
    class MyRedis():
        def __init__(self,ip,password,port=6379,db=0):
            #构造函数
            try:
                self.r = redis.Redis(host=ip,password=password,port=port,db=db)
                # r = redis.ConnectionPool(host=ip,password=password,port=port,db=db)
            except Exception as e:
                print('redis连接失败,错误信息%s'%e)
        def str_get(self,k):
            res = self.r.get(k)
            if res:
                return res.decode()
        def str_set(self,k,v,time=None):
            self.r.set(k,v,time)
        def delete(self,k):
            tag = self.r.exists(k) #判断这个key是否存在
            if tag:
                self.r.delete(k)
                print('删除成功')
            else:
                print('这个key不存在')
        def hash_get(self,name,k):
            res = self.r.hget(name,k)
            if res:
                return res.decode()
        def hash_set(self,name,k,v):
            self.r.hset(name,k,v)
        def hash_getall(self,name):
            data = {}
            # {b'12': b'1212', b'3': b'sdad', b'4': b'asdadsa'}
            res = self.r.hgetall(name)
            if res:
                for k,v in res.items():
                    k =  k.decode()
                    v = v.decode()
                    data[k]=v
            return data
        def hash_del(self,name,k):
            res = self.r.hdel(name,k)
            if res:
                print('删除成功')
                return 1
            else:
                print('删除失败,该key不存在')
                return 0
    
        @property
        def clean_redis(self):
            self.r.flushdb()  #清空redis
            print('清空redis成功!')
            return 0
    
    
    my = MyRedis('118.24.3.40','HK139232')

    总结:

    1、发邮件
        1、在你的邮箱设置里面打开smtp服务
        2、开启邮箱授权码,记住这个授权码
    
        yagmail
            要用群里我给你的那个.whl的安装包
            直接pip install的话,发中文附件的时候,文件名是乱码
    
    2、 面向对象编程  class
        面向过程编程      执行者
            1、4S店 掏钱买车
            2、保险公司 上保险
            3、税务局 交购置税
            4、交管局 验车、选号、交钱、取牌、上牌
        面向对象       指挥者
            买车办事处
                1、4S店 掏钱买车
                2、保险公司 上保险
                3、税务局 交购置税
                4、交管局 验车、选号、交钱、取牌、上牌
    
    
        类
            一个种类,一个模型。汽车模型
        对象
            指具体的东西,模型造出来的东西叫做对象。
        实例
            实例和对象是一样的。
        实例化
            实例化就是造东西的这个过程。
        属性
            就是变量
        方法
            就是类里面的函数
        继承
        封装
        多态
        self代表的是本类对象。
        因为函数里面的变量都是局部变量,出了函数就不能用了。
        用self给对象绑定了之后,就可以self.xx随便用了
    
        构造函数
            def __init__():
                pass
         构造函数就是类在实例化的时候执行的函数。
         类在实例化的时候,会自动执行它
    
        析构函数
            def __del__():
                pass
          实例被销毁的时候执行的。
    
        属性方法
            看起来像属性的一个方法。
        类变量
            类变量,公共的变量,每个实例都可以用
        实例变量(成员变量)
        实例方法
            实例化之后才可以用的。
        类方法
            1、不用实例化就可以直接调用。
            2、它可以通过cls使用类变量
            3、它不能调用这个类里面的其他实例方法和实例变量
        静态方法
            #你不想实例化的时候,就可以定义成类方法
            #静态方法就是一个普通函数,只不过是写在类里面而已,它用不了类变量、类方法、实例变量、实例方法
        私有
            私有方法
            私有变量
                出了类之后,就不能用了。
    
        if  __name__ == '__main__':
            判断这个python是在别的地方导入的,还是直接运行的这个python文件
            这句话一般是做调试的时候用的。
            1、如果是直接运行这个python文件的时候,这句话一点用都没有
            2、其他文件引用时,这个判断为false,就不会执行后面的内容
    
    3、多线程和多进程  (见day10)
    4、单元测试框架unittest  (还没有讲)
    
    
    作业:(已完成)
    代码地址:
    https://git.coding.net/lilyzhang_2018/day9homework.git 1、把我写的操作redis的类, 1、加上异常处理 2、把剩下的方法封装好 3、redis这个类day9下面私有.py文件中 2、仔细整理笔记到博客 3、选做题(见day10 基于数据的自动化测试框架) 1、读Excel,获取里面的测试用例, 2、根据Excel里面的测试用例,调用接口,把返回结果和是否通过写入Excel 3、发送测试报告到邮箱 xx你好: 本次测试共运行xxx条用例,失败xx条,成功xx条。。
  • 相关阅读:
    EventBus详解
    Java BigDecimal使用
    StringFormate使用
    Sourcetree拉取推送问题
    Android下拉刷新控件android-Ultra-Pull-To-Refresh 使用
    SourceTree跳过Atlassian账号,免登陆,跳过初始设置
    Android Studio3.2新建项目gradle read time out
    底部导航栏使用BottomNavigationBar
    PopupWindow封装
    电脑连接真机,但是androidstudio不显示手机,ADB Interface黄色感叹号
  • 原文地址:https://www.cnblogs.com/lilyzhang-2018/p/9069951.html
Copyright © 2020-2023  润新知