python学习笔记(十九)面向对象编程,类
一、面向对象编程
面向对象,是一种程序设计思想。
编程范式:编程范式就是你按照什么方式去编程,去实现一个功能。不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路,两种最重要的编程范式分别是面向过程编程和面向对象编程。
面向过程:什么是面向过程,面向过程的思想就是把一个项目,一件事情按照一定的顺序,从头到尾一步一步的做下去,先做什么,后做什么,一直到结束。这种编程思想,只要前面一个步骤变了,那么后面的就也要变,后面维护一起比较麻烦,这样的编程思想,我们在写一些简单的小程序,只执行一次的脚本时可以使用。
面向对象:面向对象的思想就是把一个项目,一件事情分成更小的项目,或者说分成一个个更小的部分,每一部分负责什么方面的功能,最后再由这些部分组合而成为一个整体。这种思想比较适合多人的分工合作,就像一个大的机关,分各个部门,每个部门分别负责某样职能,各个部门可以充分发挥自己的特色,只有符合一个前提就行。
二,面向对象的特性:
类:class
类,对比现实世界来说就是一个种类,一个模型
一个类即是对一类拥有相同属性的对象的抽象,蓝图,原型
在类中定义了这些对象的都具备的属性,共同的方法。
对象:object
对象,也就是指模型造出来的具体的东西
一个对象既是一个类的实例化后实例,一个类必须经过实例化方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之间有性,亦有不同
实例化:
初始化一个类,造了一个对象。把一个类变成一个具体的对象的过程,叫做实例化
封装:
把一些功能的实现细节不对外暴露,类中对数据的赋值,内部调用对外部用户是透明的,这使类变成了一个胶囊或者容器,里面包含着类的数据和方法
继承:
一个类可以派生出子类,在这个父类里定义的属性,方法自动被子类继承。
继承是为了代码的重用
多态:
对不同类的对象发出相同的消息将会有不同的行为。
多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来,再通过这个抽象的事物,与不同的具体事物进行对话
一种接口,多种实现
三,面向对象的好处
对于编程语言的初学者来讲,OOP不是一个很容易理解的编程方式,大家虽然都按老师讲的都知道OOP的三大特性是继承、封装、多态,并且大家也都知道了如何定义类、方法等面向对象的常用语法,但是一到真正写程序的时候,还是很多人喜欢用函数式编程来写代码,特别是初学者,很容易陷入一个窘境就是“我知道面向对象,我也会写类,但我依然没发现在使用了面向对象后,对我们的程序开发效率或其它方面带来什么好处,因为我使用函数编程就可以减少重复代码并做到程序可扩展了,为啥子还用面向对象?”对于此,我个人觉得原因应该还是因为你没有充分了解到面向对象能带来的好处。 无论用什么形式来编程,我们都要明确记住以下原则: 写重复代码是非常不好的低级行为 你写的代码需要经常变更 开发正规的程序跟那种写个运行一次就扔了的小脚本一个很大不同就是,你的代码总是需要不断的更改,不是修改bug就是添加新功能等,所以为了日后方便程序的修改及扩展,你写的代码一定要遵循易读、易改的原则(专业数据叫可读性好、易扩展)。 如果你把一段同样的代码复制、粘贴到了程序的多个地方以实现在程序的各个地方调用,这个功能,那日后你再对这个功能进行修改时,就需要把程序里多个地方都改一遍,这种写程序的方式是有问题的,因为如果你不小心漏掉了一个地方没改,那可能会导致整个程序的运行都 出问题。 因此我们知道 在开发中一定要努力避免写重复的代码,否则就相当于给自己再挖坑。 还好,函数的出现就能帮我们轻松的解决重复代码的问题,对于需要重复调用的功能,只需要把它写成一个函数,然后在程序的各个地方直接调用这个函数名就好了,并且当需要修改这个功能时,只需改函数代码,然后整个程序就都更新了。 其实OOP编程的主要作用也是使你的代码修改和扩展变的更容易,那么小白要问了,既然函数都能实现这个需求了,还要OOP干毛线用呢? 呵呵,说这话就像,古时候,人们打仗杀人都用刀,后来出来了枪,它的主要功能跟刀一样,也是杀人,然后小白就问,既然刀能杀人了,那还要枪干毛线,哈哈,显而易见,因为枪能更好更快更容易的杀人。函数编程与OOP的主要区别就是OOP可以使程序更加容易扩展和易更改。
四、类
属性:属性就是里面的一个变量,有类变量和实例变量,类变量是类在定义的时候就有的,实例变量是在实例化的时候才产生的变量。这个可以理解为,人是一个类,他的名字,年龄,性别就是它的属性
方法:方法就是类的功能,也就是定义在类里面的函数,它实现了某个功能,比如说人有睡觉的功能。
构造函数:就是类在实例化的时候做的某些初始化操作
析构函数:就是这个实例在销毁的时候做的一些操作
定义类:
定义类使用class关键字,类名一般首字母大写。
1 class Car():#模型,模板 2 def __del__(self): 3 #析构函数,这个实例被销毁的执行的。 4 print('over..') 5 6 def my_self(self): 7 print( 8 '我是一个汽车 我的颜色是【%s】,我有【%s】个窗户'%(self.color,self.window) 9 ) 10 self.price = 10002 11 def run(self): 12 print(self.color) 13 print(self.window) 14 print(self.price) 15 print('汽车在跑。。。') 16 17 def __init__(self,color,window): 18 # 19 #构造函数,是类在初始化的时候会执行它 20 #如果你的类在实例化的时候要传入一些参数,那么你就要在__init__这个函数里写参数了 21 self.color = color #绑定属性 22 self.window = window 23 print('执行我了。。') 24 25 #把模型做成实际的一个汽车,这个过程叫做实例化。 26 bus = Car('黄色','3开门') #实例化 27 bus2 = Car('黑色','4开门') #实例化 28 bus3 = Car('粉色','2开门') #实例化 29 bus.my_self() # 30 bus2.my_self() 31 bus3.my_self() 32 33 #实例就是指具体造出来的东西,通过类实例化处理的东西,就是实例 34 #对象,就是实例 35 #
继承:
1 class WssFather(object): 2 @property 3 def money(self): 4 return 10000000 5 def smoke(self): 6 self.yan = '玉溪' 7 print('抽烟') 8 def drink(self): 9 print('喝酒') 10 def tangtou(self): 11 print('烫头') 12 13 class Wss(WssFather): 14 def driver(self): 15 print('开车') 16 17 class Animal(object): 18 def eat(self,name): 19 print('吃') 20 21 22 class Brid(Animal): 23 pass
实例变量:
1 class Person(object): 2 country = 'China' #类变量 3 def __init__(self,name,age,sex): 4 self.name=name #实例变量,必须实例化之后才能用,成员变量 5 self.age=age 6 self.sex=sex 7 8 def say_my_country(self): 9 print(self.country) 10 11 print(Person.country) 12 # dsx = Person(小师妹,23,'男') 13 # print(dsx.name) 14 # print(dsx.age) 15 # print(dsx.sex) 16 # print(dsx.country) 17 # ybq = Person('绿萝',28,'男')
静态方法,类方法:
1
私有方法、私有属性:
什么是私有,私有就是只有在类里面可以访问,实例化之后不可以访问和调用,有私有方法和私有属性。私有就把变量名或者函数名前面加上"__"两个下划线,其实就是通过私有来实现封装的
import redis 2 class MyRedis(): 3 xiaohei = '哈哈哈' 4 def __init__(self,host,password='',port=6379): 5 self.__host = host #私有属性 6 self.passwd = password 7 self.port = port 8 self.__coon_redis() 9 def __coon_redis(self): #私有方法 10 self.coon = redis.Redis(host=self.__host,password=self.passwd,port=self.port) 11 def get(self,k): 12 print('__host...',self.__host) 13 return self.coon.get(k).decode() 14 15 @staticmethod #静态方法 16 def other(): 17 print('我是other') 18 @classmethod#类方法,也不需要实例化,直接就能用。它静态方法高级一点 19 #它可以使用类变量和类方法。 20 def class_fun(cls): 21 print(cls.xiaohei) 22 cls.class_fun2() 23 @classmethod 24 def class_fun2(cls): 25 print('我是类方法2') 26 # r = MyRedis('211.149.218.16','123456') 27 MyRedis.class_fun()
小练习:
#签名,作用为了作弊
#sign :82B20DE4-40C2-4859-9DBC-C93B0FBFD09C
#1.先取用户的设备号码,md5 加密一次
#2.再取加密之后前10位
#3.再加盐,再给md5一次
#4.最后生成一个字符串
1 from hashlib import md5 2 class GetSign(object): 3 slat='SDF234_&#$_12' 4 def __init__(self,device_id): 5 self.device_id=device_id 6 def md5(self,str): 7 #md5加密的 8 s=str.encode() 9 m=md5(s) 10 return m.hexdigest() 11 @property #把这个函数变成一个属性方法 ,如果这个方法没有入参,那就可以给变成一个属性方法 12 def get_res(self): 13 first_md5 = self.md5(self.device_id) 14 tmp = first_md5[:10] #取前10位 15 after_salt = tmp+self.slat 16 self.sign = self.md5(after_salt) 17 return self.sign 18 res = GetSign('82B20DE4-40C2-4859-9DBC-C93B0FBFD09C') 19 print(res.device_id) 20 print(res.get_res)
写日志:
1 import logging 2 from logging import handlers 3 4 5 class Logger(object): 6 level_relations = { 7 'debug': logging.DEBUG, 8 'info': logging.INFO, 9 'warning': logging.WARN, 10 'error': logging.ERROR, 11 'crit': logging.CRITICAL 12 } # 日志级别关系映射 13 14 def __init__(self, fp, level='debug', when='midnight', interval=1, backCount=5, encoding='utf-8'): 15 ''' 16 17 :param fp:日志文件路径 18 :param level: 日志级别 默认是debug 19 :param when: 分割日志的单位 S 秒、M 分、 H 小时、 D 天、 W 每星期(interval==0时代表星期一)、midnight 每天凌晨 20 :param interval: 时间间隔 默认每天凌晨 21 :param backCount: 备份文件个数 默认5个 22 :param encoding: 日志文件编码 23 ''' 24 self.level = self.level_relations.get(level) 25 self.logger = logging.getLogger(fp) 26 self.logger.setLevel(self.level) 27 fmt = logging.Formatter('%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s') 28 sh = logging.StreamHandler() 29 sh.setFormatter(fmt) 30 sh.setLevel(self.level) 31 th = handlers.TimedRotatingFileHandler(fp, when=when, interval=interval, backupCount=backCount, 32 encoding=encoding) 33 th.setFormatter(fmt) 34 th.setLevel(self.level) 35 self.logger.addHandler(th) 36 self.logger.addHandler(sh) 37 38 def debug(self, msg): 39 self.logger.debug(msg) 40 41 def info(self, msg): 42 self.logger.info(msg) 43 44 def warning(self, msg): 45 self.logger.warning(msg) 46 47 def error(self, msg): 48 self.logger.error(msg) 49 50 def crit(self, msg): 51 self.logger.critical(msg) 52 53 54 if __name__ == '__main__': 55 l = Logger('a.log') # 实例化 56 l.info('hehehe') # 调用 57 l.debug('哈哈哈') 58 l.error('xxx')
1 class My(): 2 def __init__(self,name): 3 self.name = name 4 self.cry() 5 def cry(self): #实例方法,必须得实例化后才可以调用 6 print('%s在哭。。。'%self.name) 7 def learn(self): 8 self.skill = ['开车'] 9 def my_self(self): 10 print('我的名字【%s】 我会%s'%(self.name,self.skill)) 11 12 wsl = My('小黑黑') # self = wsl 13 wsl.skill = '黑' 14 wsl.learn() 15 wsl.skill.append('花') 16 wsl.skill.append('话') 17 wsl.skill.append('滑') 18 wsl.my_self() 19 wsl.learn() 20 wsl.my_self() 21 22 td = My('蘑菇')
连接数据库:
1 import pymysql 2 class OpMySql1: #经典类 3 pass 4 5 class OpMySql(object):#新式类 6 def __init__(self,host,user,password,db,port=3306,charset='utf8'): 7 schema = { 8 'user':user, 9 'host':host, 10 'password':password, 11 'db':db, 12 'port':port, 13 'charset':charset 14 } 15 try: 16 self.coon = pymysql.connect(**schema) 17 except Exception as e: 18 print('数据库连接异常!%s'%e) 19 quit('数据库连接异常!%s'%e) 20 else:#没有出异常的情况下,建立游标 21 self.cur = self.coon.cursor(cursor=pymysql.cursors.DictCursor) 22 23 def execute(self,sql): 24 try: 25 self.cur.execute(sql) 26 except Exception as e: 27 print('sql有错误%s'%e) 28 return e 29 if sql[:6].upper()=='SELECT': 30 return self.cur.fetchall() 31 else:#其他sql语句的话 32 self.coon.commit() 33 return 'ok' 34 35 def __del__(self): 36 self.cur.close() 37 self.coon.close() 38 39 ybq = OpMySql('211.149.218.16','jxz','123456',db='jxz') #实例化 40 41 print(ybq.execute('select * from stu;')) 42 print(ybq.execute('select * from stu;')) 43 print(ybq.execute('select * from stu;'))
url编码:
1 import urllib.parse 2 s='besttest 自动化测试' 3 print(urllib.parse.quote(s)) #url编码 4 print(urllib.parse.quote_plus(s)) #url编码, 5 src='https://www.baidu.com/s?wd=besttest%20%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95&rsv_spt=1&rsv_iqid=0x90f615640005e9b2&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&rqlang=cn&tn=baiduhome_pg&rsv_enter=1&inputT=8129&rsv_t=0d22VbBsLUg6wkL0kNn1rPhfwhU%2F5UCRNiEBd5oqMzEh6ImgExR7fH65dNLwCf0ilzUT&rsv_sug3=36&rsv_sug1=9&rsv_sug7=100&oq=besttest&rsv_pq=f857c55a00063cfd&rsv_sug2=0&rsv_sug4=8623' 6 7 print(urllib.parse.unquote(src)) #url解码 8 print(urllib.parse.unquote_plus(src)) #url解码
self代表本类对象
修改父类的方法:
重写父类的方法的目的是为了给他扩展一些功能
核心思想就一句话,先调用一下你要重写的父类方法,然后再加新的代码就好了。
1 class Coon(object): 2 def conn(self,host,passwd): 3 print(host,passwd) 4 class Coon2(Coon): 5 def conn(self): 6 #重写父类的方法 7 print('hahahha') 8 c=Coon2() 9 c.conn() #hahahha
1 class Coon(object): 2 #基类 3 def __init__(self,host,passwd,port): 4 self.host=host 5 self.passwd=passwd 6 self.port=port 7 class CoonMySql(Coon): 8 def __init__(self,host,passwd,port,username,db,charset='utf8'): 9 Coon.__init__(self,host,passwd,port)#在调用父类的构造方法,咱们自己手动调用父类的方法 10 self.username=username 11 self.db=db 12 self.charset=charset 13 def coon_mysql(self): 14 print(self.host) 15 16 17 class Coon(object): 18 #基类 19 def __init__(self,host,passwd,port): 20 self.host=host 21 self.passwd=passwd 22 self.port=port 23 class CoonMySql(Coon): 24 def __init__(self,host,passwd,port,username,db,charset='utf8'): 25 super(CoonMySql,self).__init__(host,passwd,port)#super自动帮忙找到父类,然后调用 26 self.username=username 27 self.db=db 28 self.charset=charset 29 def coon_mysql(self): 30 print(self.host)