Python学习day26-面向对象之小结

Python学习day25-面向对象之小结

面向对象解决的问题

面向对象的编程是一种思想,主要就是用于区别面向过程这种思想。其解决的最大的问题就是程序的扩展性,因为面向过程的编程扩展起来非常的麻烦,所以才产生了面向对象这种编程思想,但编程思想并没有高低之分,并不是说我们以后所有的程序都要用面向对象的思想来完成,这是非常偏激的做法,我们应该在适当的时候选择是用面向对象还是面向过程的方法。

面向对象的编程固然解决了程序的可扩展性,但他也有其缺点,代码量大,结构构思较难等,都是真实存在的,所以根据现实情况选择最适合的编程方式才是最正确的。

类与对象

类:是一系列共同的属性和方法

对象:是属性和方法的结合体

现实生活中是先有对象,才有总结的类,但在Python中,我们要先定义类,然后派生或者说实例化产生对象。

类及对象的定义

具体实例见https://www.cnblogs.com/Xu-PR/p/11412865.html

绑定方法及非绑定方法

绑定方法的意思就是,绑定谁就给谁来用,并且会把自身作为第一个参数传进方法里去,绑定方法分为对象的绑定方法以及类的绑定方法。

非绑定方法就与之相反,即不管是对象还是类都可以调用,且不必把自己传进去作为第一个参数,实际上非绑定方法就是定义在类内部,但是就是一个普通的方法,谁都不绑定,另外,非绑定方法又叫静态方法。

绑定方法用到的装饰器是classmethod,非绑定方法用到的装饰器是staticmethod,实例如下:

 
 
 
xxxxxxxxxx
33
 
 
 
 
1
class Person:
2
'''
3
注释的内容
4
'''
5
6
def __init__(self, name, age):
7
self.name = name
8
self.age = age
9
10
def func(self):
11
print('对象的绑定方法')
12
13
@classmethod
14
def class_method(cls):
15
print('我是类的绑定方法,类调用')
16
17
# 当成一个普通函数,只不过是写在类内部的,非绑定方法,也叫静态方法
18
@staticmethod
19
def static_method():
20
print('静态方法,谁都不绑定')
21
        
22
        
23
# 绑定到对象的方法
24
u = Person('nick', 19)
25
u.def()
26
# 绑定到类的方法
27
Person.class_method()
28
# 静态方法调用:        
29
# 类来调用
30
Person.static_method()
31
# 对象来调用
32
p = Person('nick', 19)
33
p.static_method()
 
 

一般情况下,当一个方法跟类和对象都没有关系的时候,会考虑将其定义成静态方法,一般在类内部使用,当然类外部也可以使用,不过不推荐。

面向对象三大特征

继承

继承的概念

继承是一种新建类的方式,继承一个类,那么类中的属性和方法在子类中都可以使用,被继承的类叫做父类(基类),继承的类叫做子类(派生类)。继承最大的作用是减少代码量,

继承过的类分两种,即新式类和经典类,新式类是指继承了object的类,在Python3中默认都是新式类,但没有继承object的类叫做经典类,在Python2中存在,Python2中如果需要定义新式类的话就必须在括号里加上object,否则生成的就是经典类。

新式类和经典类的区别不太大,但还是有区别,最主要的区别体现在属性的查找顺序上,且只有菱形问题才有区别。菱形问题就是一个文件中所有的类都显示的继承一个类,就是大家集成到最后发现继承的都是同一个类,那么新式类和经典类的属性查找顺序就会有问题。

新式类主要是以广度优先的方式来查找属性,或者方法,即从左向右,每次往上寻找,但不找到顶点,直到最后一条继承线找完才会寻找最后一个顶点。

经典类与新式类的区别则是以深度优先的方式来查找属性,即从左开始第一条继承线就会寻找到最后顶点,然后继续向右寻找。代码及示意图如下:

 
 
 
xxxxxxxxxx
1
27
 
 
 
 
1
class A(object):
2
    def test(self):
3
        print('from A')
4
5
class B(A):
6
    def test(self):
7
        print('from B')
8
9
class C(A):
10
    def test(self):
11
        print('from C')
12
13
class D(B):
14
    def test(self):
15
        print('from D')
16
17
class E(C):
18
    def test(self):
19
        print('from E')
20
21
class F(D,E):
22
    # def test(self):
23
    #     print('from F')
24
    pass
25
f1=F()
26
f1.test()
27
print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性
 
 

新式类的查找顺序.png

重用父类的两个方法

  1. 指名道姓式,即直接用父类名.方法/属性的方式来重用父类的方法
  2. super()关键字,相当于父类名(),其查找顺序严格按照mro的列表查找

多态和多态性

多态就是一类事物的多种形态,比如动物类的猪,狗,鹿。多态增加了程序的灵活性,同时也增加了程序的可扩展性。

其实多态有时候在程序里并不是一件特别好的事情,因为项目很大的情况下,每个人分工合作,变量以及用的方法很容易名字造成冲突,所以我们要对子类的方法进行约束,让其实现父类的方法。

这里推荐两种方法:

  1. abc模块
  2. 抛异常

具体的代码示例前面博客已经写过,不再赘述。

封装

组合也是封装的一种,也就是把一些东西隐藏起来,起到保护,和隔离复杂度的作用。

Python里隐藏的方法是属性或方法前面加__,注意后面不要加,因为这不是内置属性。其中隐藏属性的目的是为了数据的安全,隐藏方法的目的则是隔离复杂度,让使用者只需要了解自己用到的方法及作用就可以了,不必了解内部用的什么原理,或者调用了多少方法。

面向对象的三个常用装饰器

其实可以说是一个装饰器,就是property,另外的setter和deleter都是依附于property存在的。

 
 
 
xxxxxxxxxx
1
29
 
 
1
class Person:
2
def __init__(self, name, height, weight):
3
self.__name = name
4
self.__height = height
5
self.__weight = weight
6
7
@property# 可以把方法封装成数据属性,即使用者调用该方法的时候会认为这是一个固定的属性,而不是一个方法这里封装的方法是name,所以下面setter和deleter调用时候都是name调用的
8
def name(self):
 
 
9
return self.__name
10
11
# 用property装饰的方法名.setter
12
@name.setter  # setter是和property组合使用,用以修改被property装饰过的方法
13
def name(self, new_name):
14
# if not isinstance(new_name, str):  # 判断第一个对象是否是某个类的对象
15
if type(new_name) is not str:
16
raise Exception('不能修改')
17
else:
18
self.__name = new_name
19
20
@name.deleter  # 和property组合使用,用以删除被装饰的隐藏值,少用,或者不用
21
def name(self):
22
# raise Exception('不能删除')
23
print('删除成功')
24
# del self.__name
25
26
27
p = Person('lqz', 1.8, 70)
28
p.name = 99
29
print(p.name)
 
 

猜你喜欢

转载自www.cnblogs.com/Xu-PR/p/11430030.html