Python学习day25-面向对象之小结
面向对象解决的问题
面向对象的编程是一种思想,主要就是用于区别面向过程这种思想。其解决的最大的问题就是程序的扩展性,因为面向过程的编程扩展起来非常的麻烦,所以才产生了面向对象这种编程思想,但编程思想并没有高低之分,并不是说我们以后所有的程序都要用面向对象的思想来完成,这是非常偏激的做法,我们应该在适当的时候选择是用面向对象还是面向过程的方法。
面向对象的编程固然解决了程序的可扩展性,但他也有其缺点,代码量大,结构构思较难等,都是真实存在的,所以根据现实情况选择最适合的编程方式才是最正确的。
类与对象
类:是一系列共同的属性和方法
对象:是属性和方法的结合体
现实生活中是先有对象,才有总结的类,但在Python中,我们要先定义类,然后派生或者说实例化产生对象。
类及对象的定义
具体实例见https://www.cnblogs.com/Xu-PR/p/11412865.html
绑定方法及非绑定方法
绑定方法的意思就是,绑定谁就给谁来用,并且会把自身作为第一个参数传进方法里去,绑定方法分为对象的绑定方法以及类的绑定方法。
非绑定方法就与之相反,即不管是对象还是类都可以调用,且不必把自己传进去作为第一个参数,实际上非绑定方法就是定义在类内部,但是就是一个普通的方法,谁都不绑定,另外,非绑定方法又叫静态方法。
绑定方法用到的装饰器是classmethod,非绑定方法用到的装饰器是staticmethod,实例如下:
xxxxxxxxxx
class Person:
'''
注释的内容
'''
def __init__(self, name, age):
self.name = name
self.age = age
def func(self):
print('对象的绑定方法')
def class_method(cls):
print('我是类的绑定方法,类调用')
# 当成一个普通函数,只不过是写在类内部的,非绑定方法,也叫静态方法
def static_method():
print('静态方法,谁都不绑定')
# 绑定到对象的方法
u = Person('nick', 19)
u.def()
# 绑定到类的方法
Person.class_method()
# 静态方法调用:
# 类来调用
Person.static_method()
# 对象来调用
p = Person('nick', 19)
p.static_method()
一般情况下,当一个方法跟类和对象都没有关系的时候,会考虑将其定义成静态方法,一般在类内部使用,当然类外部也可以使用,不过不推荐。
面向对象三大特征
继承
继承的概念
继承是一种新建类的方式,继承一个类,那么类中的属性和方法在子类中都可以使用,被继承的类叫做父类(基类),继承的类叫做子类(派生类)。继承最大的作用是减少代码量,
继承过的类分两种,即新式类和经典类,新式类是指继承了object的类,在Python3中默认都是新式类,但没有继承object的类叫做经典类,在Python2中存在,Python2中如果需要定义新式类的话就必须在括号里加上object,否则生成的就是经典类。
新式类和经典类的区别不太大,但还是有区别,最主要的区别体现在属性的查找顺序上,且只有菱形问题才有区别。菱形问题就是一个文件中所有的类都显示的继承一个类,就是大家集成到最后发现继承的都是同一个类,那么新式类和经典类的属性查找顺序就会有问题。
新式类主要是以广度优先的方式来查找属性,或者方法,即从左向右,每次往上寻找,但不找到顶点,直到最后一条继承线找完才会寻找最后一个顶点。
经典类与新式类的区别则是以深度优先的方式来查找属性,即从左开始第一条继承线就会寻找到最后顶点,然后继续向右寻找。代码及示意图如下:
xxxxxxxxxx
class A(object):
def test(self):
print('from A')
class B(A):
def test(self):
print('from B')
class C(A):
def test(self):
print('from C')
class D(B):
def test(self):
print('from D')
class E(C):
def test(self):
print('from E')
class F(D,E):
# def test(self):
# print('from F')
pass
f1=F()
f1.test()
print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性
重用父类的两个方法
- 指名道姓式,即直接用
父类名.方法/属性
的方式来重用父类的方法 - super()关键字,相当于父类名(),其查找顺序严格按照mro的列表查找
多态和多态性
多态就是一类事物的多种形态,比如动物类的猪,狗,鹿。多态增加了程序的灵活性,同时也增加了程序的可扩展性。
其实多态有时候在程序里并不是一件特别好的事情,因为项目很大的情况下,每个人分工合作,变量以及用的方法很容易名字造成冲突,所以我们要对子类的方法进行约束,让其实现父类的方法。
这里推荐两种方法:
- abc模块
- 抛异常
具体的代码示例前面博客已经写过,不再赘述。
封装
组合也是封装的一种,也就是把一些东西隐藏起来,起到保护,和隔离复杂度的作用。
Python里隐藏的方法是属性或方法前面加__
,注意后面不要加,因为这不是内置属性。其中隐藏属性的目的是为了数据的安全,隐藏方法的目的则是隔离复杂度,让使用者只需要了解自己用到的方法及作用就可以了,不必了解内部用的什么原理,或者调用了多少方法。
面向对象的三个常用装饰器
其实可以说是一个装饰器,就是property,另外的setter和deleter都是依附于property存在的。
xxxxxxxxxx
class Person:
def __init__(self, name, height, weight):
self.__name = name
self.__height = height
self.__weight = weight
# 可以把方法封装成数据属性,即使用者调用该方法的时候会认为这是一个固定的属性,而不是一个方法这里封装的方法是name,所以下面setter和deleter调用时候都是name调用的
def name(self):
return self.__name
# 用property装饰的方法名.setter
setter # setter是和property组合使用,用以修改被property装饰过的方法.
def name(self, new_name):
# if not isinstance(new_name, str): # 判断第一个对象是否是某个类的对象
if type(new_name) is not str:
raise Exception('不能修改')
else:
self.__name = new_name
deleter # 和property组合使用,用以删除被装饰的隐藏值,少用,或者不用.
def name(self):
# raise Exception('不能删除')
print('删除成功')
# del self.__name
p = Person('lqz', 1.8, 70)
p.name = 99
print(p.name)