python面向对象三大特性
- 封装
类里面不光有属性还有方法。这种将属性通过方法直接在类内部操作的形式叫做封装。这里的封装是把属性封装在类内部。这样对类形成了一种“黑盒”状态,我们不需要知道类内部是什么样的。只要对对象进行操作就可以。比如数据访问限制,既想将数据保护起来(设置私有属性:self.__属性名 self.__方法名),又想在一定程度上对数据进行操作。这里就可以用到这个特性,我们可以在类中,设定一个方法,getName()来得到数据,setName()来设置数据。[注]:父类的私有属性和私有方法,子类无法对其进行修改,只能修改父类属性、方法的类型或者子类对其父类的方法进行重写。例子:
class People(object):
def __init__(self,name):
self.__name = name
def getName(self):
return self.__name
def setName(self,newName)
self.__name = newName
xiaoming = People("小明")
print(xiaoming.__name)
>>>AttributeError:'people' object has no attribute '__name'
xiaoming.setName("xiaoxiaoming")
print(xiaoming.getName())
>>>xiaoxiaoming
- 继承
面向对象中的继承就是继承的类直接拥有被继承类的属性而不需要在自己的类体中重新再写一遍,其中被继承的类叫做父类、基类,继承的类叫做派生类、子类。在python3中如果不指定继承哪个类,默认就会继承Object类,而继承了Object类的类就叫做新式类,而在python2中如果不指定继承哪个类也不会默认去继承Object类,而没有继承Object类的类就叫做经典类。经典类和新式类的不同就在于对方法的搜索顺序不同,经典类是深度优先即先找自己类内,如果没有就找左边第一个父类,没找到继续从这个父类的父类中找依次类推直到找到最上一级的父类也没找到再找左边第二个父类,然后再重复之前的过程,直到所有父类找一遍没找到就报错;而新式类是广度优先,当下一个类可以通过其他类找到时就先不去找它,而是找继承关系中与它的子类同级的其他类,依次类推直到最后找到object类没有找到指定方法就报错。新式类搜索顺序图示如下,还可以通过 类名.mro() 查看新式类继承中的属性搜索顺序。
单继承与多继承:
在其他语言中只支持单继承即class 类名(父类名),而python支持多继承,用逗号将多个父类隔开即class 类名(父类名1,父类名2,。。。。)。例子:
class Ma(object):
def run(self):
print("--------------30km/h")
class Lv(object):
def run(self):
print("--------------15km/h")
class Nuozi(Lv,Ma):
def test(self):
return nuozi.run()
nuozi = Nuozi()
nuozi.test()
>>>--------------15km/h #继承多个父类的第一个父类,详见多继承见: 印象笔记-------MOR
继承与抽象:
抽象就是把一类事物的共有特性提取出来,继承则是把父类的属性拿过来并且还拥有自己的属性。抽象是包含的范围越来越大,共性越来越少,继承则是包含的返回越来越小,共性越来越多。我们定义父类的过程就是抽象,定义子类的过程就是继承。
重写:
我们把子类有而父类没有的方法叫做子类的派生方法,而父类有子类也有的方法叫做对父类方法的重写,因为按照类方法的搜索顺序一个方法如果在子类中有就不会再从父类中找了,结果就是父类中的方法无法调用了,如果既想执行父类中的方法同时在子类中又能定义新功能,就需要先把父类中的这个方法单独继承过来,在python中只能使用父类名.方法名(self,父类的其他参数)的方式,在python3中可以使用super函数来实现,比如super().父类方法名(除self外的其他参数),其实在super函数中还需要传入子类名和子类对象(在类中用self),但是我们使用时不需要特意去传,除非在类外单独调用父类的方法。注意在继承父类方法时父类的参数除了需要在父类的方法中传递还需要在子类重写的方法中传递。例子:
class Animal:
def __init__(self,name,life_value):
self.name = name
self.life_value = life_value
class Person(Animal):
def __init__(self,money,name,life_value):
super().__init__(name,life_value,aggr)
self.money = money
- 多态
定义方法时候的类型(继承父类)跟实际运行时调用的方法类型不一样