面向对象的三大特征:封装、继承、多态
1、封装
(1)类的封装特征
隐藏对象的属性和实现细节,只对外提供必要的方法。
通过“私有属性、私有方法”的方式,实现“封装”。Python 追求简洁的语法
class game:def __init__(self,type):self.type=type #type是类对象中的一个实例属性def start(self):print('正在启动游戏......,启动成功')'''上面写到的方法都被包在game类里面,都隶属与game类,这就叫做封装'''
game1=game('动作冒险')
game1.start()
print(game1.type)
一开始类中的方法被打包在了类里面,这就叫做封装;后面使用了类当中封装包装的属性和方法
(2)若某个属性不想被该类对象外部访问,则在前面加两个'_'
class Students:def __init__(self,name,age):self.name=nameself.__age=age #不想让外部访问def process(self):print('该应用在半小时内禁止被访问')stu1=Students('张三',20)
print(stu1.name)
print(stu1.__age) #AttributeError: 'Students' object has no attribute '__age'
'''在Students对象中没有找到age这个属性 因为代码遇到__age时程序就知道这个变量不能被外部使用'''
(3)虽然可以限制对象不被外部访问,但这只是我希望的情况,但实际上这个对象还是可以被使用,通过过dir()方法可以找到能使用对象的类似对象名
print(dir(stu1))['_Students__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__', 'name', 'process']
在这一大堆结果里面,'_Students__age'这个对象名的效果就跟age一样,可以被使用,并且两者的结果都是一样的
print(stu1._Students__age) #20
总结:已经被设置了不被外部访问的变量,在外部仍可以通过‘_类名__被限制外部访问的变量名’进行访问
封装的意义全靠自己自觉,看到变量限制访问了你就别去用了,完全靠自觉性
2、继承
在Python中支持多重继承,一个子类可以继承多个父类。继承语句的写法格式如下:
class 子类类名(父类类名1,父类类名2......)
类体
如果在类定义中没有指定父类,则默认父类是 object 类。也就是说,object 是所有类的父
类,里面定义了一些所有类共有的默认实现,比如:__new__()。
在刚开始学习类和对象的时候,在写完类名后都没有跟括号,代表着他们都使用的默认继承object
再上图的树状图中,从上到下他们依次具有继承的关系
在子类中使用super().方法调用父类所构造的函数 格式:super().方法名
对继承的详细解释参考下文
python继承(super()、多继承、钻石继承)_patrick_wang_bigdata的博客-CSDN博客https://blog.csdn.net/qq_23120963/article/details/105452376
(1)单继承:代码如下:
#定义父类
class Bookstore(object): #Person继承默认object类def __init__(self,bookname,order):self.bookname=booknameself.order=orderdef Book(self):print(self.bookname,self.order)print('欢迎小主光临寒舍,请随意看看,祝您消费愉快')#定义子类
class Book(Bookstore): #继承的是父类Bookstoredef __init__(self,bookname,order,type):super().__init__(bookname,order)self.type=type#定义第二个子类
class people(Bookstore):def __init__(self,name,bookname,order,time):super().__init__(Bookstore)self.name=nameself.time=timebook=Book('百科全书',2,'冒险')
person=person('张三','维基词典',2,20190101)book.info()
person.info()百科全书 2
欢迎小主光临寒舍,请随意看看,祝您消费愉快
维基词典 2
欢迎小主光临寒舍,请随意看看,祝您消费愉快
继承关系
(2)多继承:
class A(object):pass
class B(object):pass
class C(A,B):pass
(3)方法重写
子类想要输出自己独有的东西(变量),父类不能满足子类自身的需求,那么子类就学要重写方法
在子类中重新定义一个方法,左面就会出现一个向上的箭头,写明Overrides method in 父类名,意思为重写父类名中的方法;同时在父类名左面也会出现一个向下的箭头,意思为该父类方法在某个子类中被重写过
子类出现的提示
父类出现的提示
在上面继承那一块的代码上加做修改,就可以得到下面的代码
class Bookstore(object): #Person继承默认object类def __init__(self,bookname,order):self.bookname=booknameself.order=orderdef info(self):print(self.bookname,self.order)
'''Bookstore这个父类同时被Book类和person类方法重写'''#定义子类
class Book(Bookstore): #继承的是父类Bookstoredef __init__(self,bookname,order,type):super().__init__(bookname,order)self.type=type#重写方法#子类中想要输出自己独有东西,而父类不能满足,则需要对父类重写方法,重新定义一个方法def info(self):#在重写的过程中还想使用父类方法中的方法提,只需要调用即可,使用super().方法名的方式进行调用super().info()print('书的类型为:',self.type)
1
#定义第二个子类
class person(Bookstore):def __init__(self,name,bookname,order,time):super().__init__(bookname,order)self.name=nameself.time=time#重写方法def info(self):super().info()print('购买时间为{0}'.format(self.time))book=Book('百科全书',2,'冒险')
person=person('张三','维基词典',2,'2019年10月25日')book.info()
person.info()百科全书 2
书的类型为: 冒险
维基词典 2
购买时间为2019年10月25日
3、多态
以封装和继承为前提,不同的子类对象调用相同的方法,产生不同的执行结果
多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数(面向对象的方法中一般为多态性):向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为,这样就会输出不同的信息
即使类和类之间类型不同,但里面有着相同的方法。不同的对象,调用相同的方法,产生不同的执行结果,增加代码的灵活度
(1)多态的特点:
- 多态可以增加代码的灵活度
- 以继承和重写父类方法为前提
- 是调用方法的技巧,不会影响到类的内部设计
(2)实例代码
class Animal(object):def eat(self):print('动物爱吃的东西')
class Dog(Animal): #Dog类继承Animal类def eat(self):print('狗吃骨头...')
class Cat(Animal): #Cat类继承Animal类def eat(self):print('猫吃鱼...')class person: #没有继承任何类,只默认继承object类def eat(self):print('人吃五谷杂粮,鱼肉海鲜')'''在外部定义一个函数fun()'''
def fun(anyobject): #随便往函数里传一个对象anyobject.eat()fun(Dog())
fun(Cat())
fun(Animal())
print('------------------------')
fun(person()) #person类与其他类没有继承关系,但person中有eat方法,所以也会调用person里面的eat方法狗吃骨头...
猫吃鱼...
动物爱吃的东西
------------------------
人吃五谷杂粮,鱼肉海鲜
(3)“鸭子类型”
“鸭子类型”的程序不会检查对象的类型,只要你这个类里有所你调用的方法,就可以被正确的调用
就比如说上面的代码,fun()函数可以接受任意一个类型的对象(就是类),并且调用eat方法,它不关心你调用的是谁,它只管心这个对象里面有没有我需要被调用的对象
有一个函数调用Dog类,并利用到了方法eat()。我们传入Person类也一样可以运行,函数并不会检查对象的类型是不是Dog/Cat/Animal,只要他拥有eat()方法,就可以正确的被调用
鸭子类型的几个简单代码实现
python什么是鸭子类型_杰森斯坦森1150的博客-CSDN博客_python鸭子类型https://blog.csdn.net/guiyin1150/article/details/122313754
浅谈python中的多态_python_脚本之家 (jb51.net)https://www.jb51.net/article/214923.htm