这里写目录标题
Python 是面向对象的语言,也支持面向对象编程的三大特性:继承、封装(隐藏)、多态。
一、面向对象之封装
隐藏对象的属性和实现细节,只对外提供必要的方法。相当于将“细节封装起来”,只 对外暴露“相关调用方法”。
通过前面学习的“私有属性、私有方法”的方式,实现“封装”。Python 追求简洁的语法,没有严格的语法级别的“访问控制符”,更多的是依靠程序员自觉实现。
二、面向对象之继承
继承是面向对象程序设计的重要特征,也是实现“代码复用”的重要手段。 如果一个新类继承自一个设计好的类,就直接具备了已有类的特征,就大大降低了工作 难度。已有的类,我们称为“父类或者基类”,新的类,我们称为“子类或者派生类”。
1. 语法格式
Python 支持多重继承,一个子类可以继承多个父类。继承的语法格式如下:
class 子类类名(父类 1[,父类 2,...]):
类体
如果在类定义中没有指定父类,则默认父类是 object 类。也就是说,object 是所有类的父类,里面定义了一些所有类共有的默认实现,比如:__new__()
。
定义子类时,必须在其构造函数中调用父类的构造函数。调用格式如下: 父类名.__init__(self, 参数列表)
那个代码测试一下:
class Person(object):
def __init__(self, name, age):
self.name = name
self.__age = age
def say_age(self):
print(self.name, "的年龄是:", self.__age)
class Student(Person):
def __init__(self, name, age, gender):
self.gender = gender
Person.__init__(self, name, age)
stu1 = Student('VN', 10, 'man')
print(stu1.name)
print(stu1.gender)
stu1.say_age()
结果:
VN
man
VN 的年龄是: 10
['_Person__age', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'gender', 'name', 'say_age']
2. 类成员的继承和重写
- 成员继承:子类继承了父类除构造方法之外的所有成员。
- 方法重写:子类可以重新定义父类中的方法,这样就会覆盖父类的方法,也称为“重写”
class A:
def __init__(self):
self.num = 1
def info_print(self):
print('我是子类的info方法')
class B(A):
def info_print(self):
print('我是子类的info方法')
result = B()
result.info_print()
print(result.num)
结果:
我是子类的info方法
1
3. 重写__str__()方法
object 有一个__str__()方法,用于返回一个对于“对象的描述”,对应于内置函数 str() 经常用于 print()方法,帮助我们查看对象的信息。其实__str__()可以重写
上述的代码如果我们直接打印对象的话:
print(result)
结果:
<__main__.B object at 0x00000247B57DEC18>
重写之后:
class A:
def __init__(self):
self.num = 1
def info_print(self):
print('我是子类的info方法')
class B(A):
def info_print(self):
print('我是子类的info方法')
def __str__(self):
return '我是个B'
result = B()
print(result)
result.info_print()
print(result.num)
结果:
我是个B # 不重写会打印<__main__.B object at 0x00000247B57DEC18>
我是子类的info方法
1
4. 多重继承
class A:
def aa(self):
print("aa")
class B:
def bb(self):
print("bb")
class C(B,A):
def cc(self):
print("cc")
c = C()
c.cc()
c.bb()
c.aa()
结果:
cc
bb
aa
多重继承的话不是特别推荐使用,因为会把结构变得非常的复杂。
5. MRO
Python 支持多继承,如果父类中有相同名字的方法,在子类没有指定父类名时,解释器将 “从左向右”按顺序搜索。
MRO(Method Resolution Order):方法解析顺序。 我们可以通过 mro()方法获得 “类的层次结构”,方法解析顺序也是按照这个“类的层次结构”寻找的。
6. super()
在子类中,如果想要获得父类的方法时,我们可以通过 super()来做。
super()代表父类的定义,不是父类对象。
语法:
super().方法名()
使用super()的好处就是再对代码进行修改如果修改了父类的名字不需要再子类里面进行修改。
三、面向对象之多态
1. 多态
多态是指同一个方法调用由于对象不同会产生不同的行为。
- 多态是方法的多态,属性没有多态。
- 多态的存在有 2 个必要条件:继承、方法重写。
测试一下:
class Animal:
def shout(self):
print("动物叫了一声")
class Dog(Animal):
def shout(self):
print("小狗,汪汪汪")
class Cat(Animal):
def shout(self):
print("小猫,喵喵喵")
def animal_shout(a):
if isinstance(a, Animal):
a.shout() # 传入的对象不同,shout 方法对应的实际行为也不 同。
animal_shout(Dog())
animal_shout(Cat())
结果:
小狗,汪汪汪
小猫,喵喵喵
2. 特殊方法和运算符重载
Python 的运算符实际上是通过调用对象的特殊方法实现的。比如:
a = 20
b = 30
c = a+b
d = a.__add__(b)
print("c =",c)
print("d =",d)
结果:
c = 50
d = 50
常见的特殊方法:
所谓的重载其实就是自己定义个规则:
class Mynumber:
def __init__(self,v):
self.data = v
def __repr__(self): #消除两边的尖括号
return "Mynumber(%d)"%self.data
def __add__(self,other):
'''此方法用来制定self + other的规则'''
v = self.data + other.data
return Mynumber(v) #用v创建一个新的对象返回给调用者
def __sub__(self,other):
'''此方法用来制定self - other的规则'''
v = self.data - other.data
return Mynumber(v)
n1 = Mynumber(100)
n2 = Mynumber(200)
# n3 = n1 + n2
n3 = n1+n2 # n3 = n1.__add__(n2)
print(n3) #Mynumber(300)
n4 = n3 - n2 #等同于n4 = n3.__sub__(n2)
print("n4 = ",n4)
四、学习体会
面向对象实际上是一种思维逻辑的转变。这种抽象的思维要从一开始学习编程的时候建立起来。这样在以后的编码过程中才会自觉的遵守这种规则。总而言之,还是多写多练吧,总会有收获的!!!