python面向对象三大特性之继承、多态、封装
一、继承
什么是继承
所谓继承指提供了同一类对象共性的处理方法,子类继承父类共性的东西。 这样有利于代码的复用性,即子类拥有父类的方法。通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。
继承可以想象成什么是什么的关系
python中类的继承分为:单继承和多继承
class Parent1: # 父类1
pass
class Parent2: #父类2
pass
class Son1(Parent1): #单继承,基类是ParentClass1,派生类是Son1
pass
class Son2(Parent1,Parent2): #多继承,父类是Parent1和Parent2,派生类是Son2
pass
查看继承
>>> Son1.__bases__ #__base__只查看从左到右继承的第一个父类,__bases__则是查看所有继承的父类 (<class '__main__.Parent1'>,) >>> Son2.__bases__ (<class '__main__.Parent1'>, <class '__main__.Parent2'>)
如果没有指定基类,python的类会默认继承object类,object是所有python类的基类
>>> Parent1.__bases__
(<class 'object'>,)
# class Animal:
# def __init__(self,name,eat,drink,push,shit):
# self.name=name
# self.eat= eat
# self.drink= drink
# self.push= push
# self.shit= shit
# class Dog(Animal):
# def cry(self):
# print('%s汪汪汪'%self.name) #在子类中可以使用父类继承的name
# class Cat(Animal):
# def cry(self):
# print('%s喵喵喵'%self.name)
#
# teddy=Dog('泰迪','吃','喝','拉','撒')
# cat1=Cat('加菲','吃','喝','拉','撒')
# print(cat1.name) #调用属性无需添加()
# teddy.cry() #调用方法需要添加(),因为方法本质是函数
加菲
泰迪汪汪汪
在python3中,子类执行父类的方法也可以直接用super方法.
# class Animal: # def __init__(self,name,eat,drink,push,shit): # self.name=name # self.eat= eat # self.drink= drink # self.push= push # self.shit= shit # def run(self): # print('%s running'%self.name) # class Dog(Animal): # def cry(self): # super(Dog,self).run() #super(Dog,self).run() =Animal().run(self)=super().run() 执行父类的方法 # print('%s汪汪汪'%self.name) # class Cat(Animal): # def cry(self):
super().__init() #执行父类的属性 # print('%s喵喵喵'%self.name) # # teddy=Dog('泰迪','吃','喝','拉','撒') # cat1=Cat('附近反','吃','喝','拉','撒') # print(teddy.name) # teddy.cry()
多继承顺序
python3以上(新式类): 广度优先
python2(经典类) :深度优先
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__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性
<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>
#新式类继承顺序:F->D->B->E->C->A #经典类继承顺序:F->D->B->A->E->C #python3中统一都是新式类 #pyhon2中才分新式类与经典类
多态
什么是多态:相同方法调用,执行不同动作
向不同的对象发送同一条消息(!!!obj.func():是调用了obj的方法func,又称为向obj发送了一条消息func),不同的对象在接收时会产生不同的行为(即方法)。 也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。
import abc
class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
@abc.abstractmethod
def talk(self):
pass
class People(Animal): #动物的形态之一:人
def talk(self):
print('say hello')
class Dog(Animal): #动物的形态之二:狗
def talk(self):
print('say wangwang')
class Pig(Animal): #动物的形态之三:猪
def talk(self):
print('say aoao')
def func(object)
object.talk() #我们可以定义一个统一的接口来使用 三个类都有talk的方法
封装
什么是封装:
所谓封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。。封装是面向对象的特征之一,是对象和类概念的主要特性。 简单的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。
在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)
私有静态变量设置:设置静态的私有变量就是 变量名前面添加双下划线(例如:__Staic),设置私有变量后不要在类的外面调用,因为我们设置私有的就是为了不让外面的人用到此变量,并且我们也不能在一个类的外部创建一个“私有”的变量,,如果非要在外部调用的话也可以方法详见下面的例子:
#!/usr/bin/python
# -*- encodeing:utf-8 -*-
class A:
STATIC = 'aaa' # 正常的静态变量
__S = 'caoyf' # 私有的变量
def func(self):
print(A.__S) #在类的里面正常调用类的变量,如果在类的里面调用python会自动给我们进行变形,其实A.__S = A._A__S
# print(A.__S) # 使用此种方法调用会报错,因为私有变量原则上来讲不能在外部调用
print(A.__dict__) #使用这种方法打印时可以看到A.__S已经转移成'_A__S'了
print(A._A__S) #如果非要在外部调用可以使用此种方法。
A.__Cao = 'aaaaaaa' # 外部不能创建一个私有的变量
print(A.__Cao)
c = A()
c.func()
私有对象属性和私有方法:设置这些和设置私有变量时一样,私有的静态变量、对象属性 、方法都是共有一下共同点:
私有的 只能在类的内部定义和使用
__名字
在类外部使用私有静态变量 _类名__私有的名字
私有的名字 不能被子类继承 具体实例如下:
#!/usr/bin/python
# -*- encodeing:utf-8 -*-
class B:
def __init__(self,name,pwd):
self.name = name
self.__pwd = pwd # 创建对象的私有属性
def get_pwd(self): # 创建一个方法
print(self.__pwd) # 查看pwd这个私有属性
b = B('caoyf','123.com')
b.get_pwd()
print(b._B__pwd) # 当在类外部的时候,我们也不能直接使用对象的私有属性
class C:
def __ppt(self): #创建一个私有的方法
print('ppt')
def open(self):
self.__ppt()
print('打开文件')
c = C()
c._C__ppt() # 不能直接调用
c.open()
property:
定义:将一个方法伪装成一个属性,这里有提供了两种对私有的修改和删除方法,修改:方法名.setter 删除:方法名.deleter,具体的实例如下:
#!/usr/bin/python
# -*- encodeing:utf-8 -*-
class Person:
def __init__(self,name,height,witeght):
self.name = name
self.__height = height
self.__witeght = witeght
@property # 使用此方法伪装成属性
def jisuan(self):
print(self.__witeght / (self.__height * 2))
cao = Person('caoyf',1.67,82)
# cao.jisuan() # 正常调用方法是实例化的名字.方法()
cao.jisuan #伪装成属性后调用方法不需要添加括号
class Foo:
def __init__(self,name):
self.__name = name # 设置私有属性
@property # 使用此方法伪装成属性
def name(self):
print(self.__name)
@name.setter #使用setter方法 修改私有属性的名字,但是方法名一定要与源来的方法名字一直
def name(self,new_name):
self.__name = new_name
@name.deleter #使用deleter方法 删除私有属性的名字,但是方法名一定要与源来的方法名字一直
def name(self):
raise TypeError('Can not delete')
a = Foo('caoyf')
# a.name
# a.name = 'caosy'
del a.name
a.name
未完待续。。。。。。。。。。。。
本文来自博客园,作者:曹艳飞,转载请注明原文链接:https://www.cnblogs.com/caoyf1992/p/8522917.html