Python-面向对象的概念

一、面向过程和面向对象的区别

面向过程和面向对象的区别,我们用一个比较直观的例子解释一下。

面向过程是一步步执行的,比如,我们买车上牌照,面向过程的步骤就是:

 1、先去4s店,买车;2、去保险公司,上保险;3、去税务局,交置购税;4、去交管局,验车、选号、交钱、上牌。

这个过程必须按顺序进行,要去4个地方。

面向对象是一站式的,我们只需要去买车办事处,然后在这个办事处完成上面的4个过程,不需要来回跑。

二、几个名词解释

类:可以理解为一个模型,比如月饼模具。

对象:指的是具体的东西,模型造出来的东西,比如在这个模型里造出来的月饼。

实例:实例就是对象。

实例化:造东西的过程。

属性:类里面的变量。

方法:类里面的函数。

构造函数:def__init__(),是非必须的,在类实例化的时候自动执行。

析构函数: def __del__(),实例被销毁时执行。

举例:

class Bird:#类名一般首字母大写
    def __init__(self,name):#构造函数,非必须
        print('self的id是:',id(self))
        self.name = name
        self.wing = 2
    def fly(self):
        print('{}会飞'.format(self.name))
        self.eat()#调用类中的函数
    def eat(self):
        print('虫子')

# 类在用的时候,必须先实例化
if __name__ == '__main__':
    xq = Bird(name='喜鹊')#实例化:类名+括号
    print('xq的id是:',id(xq))
    xq.eat()
    xq.fly()
    print(xq.name)

运行结果为:

解析:

1、类名一般首字母大写;

2、类中的方法是无序的。例子中eat方法在最后面,仍然可以被其他方法调用;

3、类必须先实例化才可用。

4、self:代表的是本类对象,也可以理解为实例化之后的对象,在整个class都能使用。可以看到,self的id和实例化之后的对象xq是完全一样的。

5、顺便介绍一个和类无关的知识点。if __name_ == 'main':一般调试的时候用,直接运行这个python文件时会执行,如果是导入这个python文件,不执行这部分。

     在这个python文件中打印一下__name__,会发现结果是main,所以直接运行时会执行。如果是导入的,打印出来是__main__,因此不会执行这部分代码。

三、一个类的例子

例:要求把请求的数据进行编码。请求数据为: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,其中1697是商家编码。

编码规则为:

1、将商家编码(vendorId)1697进行两次MD5加密得到一个字符串 Astr
2、将请求数据
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
进行urlDecode处理(编码格式为utf-8)得到一个字符串urlDecodeStr
3、urlDecodeStr + Astr 拼接得到一个待加密的字符串 beforeMD5
4、将 beforeMD5字符串进行加密得到最终的签名

分析:1、获取到数据后,首先我们要提取商家编码;2、将商家编码2次MD5加密;3、将请求数据urlDecode;4、拼接字符串,再MD5加密

首先我们用面向过程的方法来实现,如下:

import hashlib
from urllib import parse

def my_md5(s):
    md = hashlib.md5()#实例化
    md.update(s.encode())
    return md.hexdigest()

def GetVendorId(req_data):
    vendor = req_data.split('&')[0]
    vendorId = vendor.split('=')[-1]
    return vendorId

def SignRule(req_data):
    vendorId = GetVendorId(req_data)
    Astr = my_md5(my_md5(vendorId))
    urlDecodeStr = parse.quote_plus(req_data)
    beforeMD5 = Astr + urlDecodeStr
    res = my_md5(beforeMD5)
    return res

data = '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'
res = SignRule(data)
print(res)

my_md5()和GetVendorId()函数必须在SignRule()函数前面,否则会报错。用类则不会出现这个问题,上面说过,类中的方法是无序的。

用类来实现如下:

import hashlib
from urllib import parse

class SignRule(object):
    def __init__(self,req_data):
        self.req_data = req_data #这里写了self的话,在其他函数里面也可以用,因此其他函数不需要再写一次入参
        self.GetVendorId()

    def md5(self,s):
        md = hashlib.md5()  # 实例化
        md.update(s.encode())
        return md.hexdigest()

    def GetVendorId(self):
        vendor = self.req_data.split('&')[0]
        self.vendorId = vendor.split('=')[-1]
        return self.vendorId

    def GetSign(self):
        Astr = self.md5(self.md5(self.vendorId))#如果函数不调用的话,没办法执行,也就无法获取VendorId。
#不过在构造函数里已经调用了该函数,所以不会报错。
                             #如果构造函数未调用GetVendorId,则需要在这一句前面加一句 self.GetVendorId
urlDecodeStr = parse.quote_plus(self.req_data) beforeMD5 = Astr + urlDecodeStr self.res = self.md5(beforeMD5) return self.res if __name__ == '__main__': data = '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' a = SignRule(data) print(a.GetSign())

 四、类的另一个例子---操作数据库

用面向过程的方法写操作数据库的脚本,有个缺点就是,我执行一次sql语句,就要连接和断开一个数据库。

用类可以解决这个问题,连接数据库的操作可以写在构造函数里,断开数据库的操作写在析构函数里。

代码如下:

import pymysql
class MyDb(object):
    def __init__(self,
                 host,user,passwd,db,
                 port=3306,charset='utf8'):
        try:
            self.coon = pymysql.connect(
                host=host, user=user, passwd=passwd, port=port, charset=charset, db=db,
                autocommit=True  # 自动提交
            )
        except Exception as e:
            print('数据库连接失败:{}'.format(e))
        else:
            self.cur = self.coon.cursor(cursor=pymysql.cursors.DictCursor)
    def ex_sql(self,sql):
        try:
            self.cur.execute(sql)
        except Exception as e:
            print('sql语句有问题,{}'.format(sql))
        else:
            self.res = self.cur.fetchall()
            return self.res

    def __del__(self):#析构函数,实例被销毁的时候执行
        self.cur.close()
        self.coon.close()

比如我要执行2条sql,如下图。在这些都执行结束之后,才会执行__del__()下的代码,因此只需连接一次sql,断开1次sql。

 

posted @ 2019-09-11 19:54  wind1004  阅读(671)  评论(0编辑  收藏  举报