python面向对象三

继承

继承的简介

  • 可以提高代码的复用性
  • 让类与类之间产生了关系,有了这层关系,才有了多态
  • 继承是面向对象的三大特性之一

如果在原来类的基础上,想增加一些功能,或是很多类中有大量重复的功能

  • 直接修改原类,修改起来比较麻烦,且会违反ocp原则
  • 直接创建一个新类,也比较麻烦,大量重复的代码
  • 新的类继承原来的类,继承原类的属性和方法
    如何使用继承
    定义类时,可以在类后面加上括号,括号内指定的是当前类的父类(超类,基类,super)
class Animal():
    def Run(self):
        print('狗狗跑')
    def Sleep(self):
        print('狗狗睡着了')

class Dog(Animal):
    def Home(self):
        print('狗看家')
d = Dog() # 通过Dog类对象,创建新的对象d
d.Run() # 通过实例d调用Animal中的Run方法
d.Home() # 通过实例d调用Dog中的Home方法
r = isinstance(d, Dog) # isinstance可以检查实例d是不是Dog的实例对象
print(r)
r1 = isinstance(d, Animal) # d即是Dog的实例也是Animal的实例
print(r1)
r2 = isinstance(Dog(), Animal) # 检测Dog(),是不是Animal的对象,他可以检测继承
print(r2)
# 狗狗跑
# 狗看家
# True
# True
# True

isinstance()

  • 用来判断一个对象是否是一个已知的类型】
  • 与type类似,区别在于:
  • type()不会认为子类是一种父类类型,不考虑继承关系
  • isinstance()考虑继承关系

object

  • 如果在创建类的时候省略了父类,则默认父类是object
  • object是所有类的父类,所有的类都继承object

issubclass

  • 检查一个类是不是另一个类的子类
class A:
    pass
class B(A):
    pass
r = issubclass(B, A)
print(r)
# True

方法的重写

如果在子类中有和父类重名的方法,通过子类的实例去调用方法时,会调用子类的方法而不是父类的方法,这个特点称之为方法的重写(覆盖 cover)

class A:
    def Call(self):
        print('A')
class B(A):
    def Call(self):
        print('B')
# class C(B):
    # def A(self):
    #     print('C')
b = B()
b.Call()
#B

当我们去调用一个方法时

  • 会优先在当前对象中寻找是否有该方法,如有,则调用
  • 若无,则去当前对象的父类中寻找,有,则调用
  • 若无,则去父类中的父类寻找,有,则调用,以此类推,知道找到object,如依然没有则报错
class A:
    def Call(self):
        print('A')
class B(A):
    pass
class C(B):
    pass
c = C()
c.Call()
# A

super

父类中的所有方法都会被子类继承,包括特殊方法

class Hero():
    def __init__(self, name):
        self._name = name
    def Power(self):
        print('control')
    @property
    def getter(self):
        return self._name
     # xxx.setter,xxx是getter方法的函数名   
    # name.setter,可以让setter方法直接用调用属性的方法调用,
    # 且会将修改后的返回值返回给getter方法,并执行getter方法
    @getter.setter
    def updata(self, name):
        self._name = name
class Dc(Hero):
    pass
d = Dc('spiderman')
print(d.getter)
# spiderman

那么我们是否可以直接调用父类的__init__来初始化父类中的属性?
当然可以

class Hero():
    def __init__(self, name):
        self._name = name
    def Power(self):
        print('control')
    @property
    def getter(self):
        return self._name
    @getter.setter
    def updata(self, name):
        self._name = name
class Dc(Hero):
    def __init__(self, name, age): # 我们调用了父类中的name同时加入了新的属性,但新的属性不会返回
        self._name = name 
        self._age = age
d = Dc('batman', 36)
print(d.getter)

如果父类里有多个初始化属性,那我每个初始化属性都要重新打一遍,太麻烦
引入super

  • super()可以获取当前类的父类
  • 通过super()返回的对象,调用父类时不用加self,能省点事儿,能省一点是一点
class Hero():
    def __init__(self, name, age, surpower):
        self._name = name
        self._age = age
        self._surpower = surpower
    def Introduce(self):
        print('名字{} 年龄{} 超能力{}'.format(self._name, self._age, self._surpower))
    @property
    def getter(self):
        return self._name, self._age, self._surpower # 已元组的形式返回
    @getter.setter
    def updata(self, name, age, surpower):
        self._name = name
        self._age = age
        self._surpower = surpower
class Dc(Hero):
    def __init__(self, name, age, superpower, position):
        super().__init__(name, age, superpower)
        self._position = position
    @property
    def p_get(self):
        return self._position
    @p_get.setter
    def p_set(self,position):
        self._position = position
d = Dc('batman', 36, 'rich', 'c位')
print(d.getter)
print(d.p_get)
# ('batman', 36, 'rich')
# c位

多重继承

  • 在python中是支持多重继承的,也就是我们可以为一个类同时指定多个父类(认多个爹)
  • 在开发中,没有特殊情况不要使用多重继承,因为多重继承会让我们的代码过于复杂
  • 如果多个父类中有重名的方法,则先会在第一个父类中寻找,然后是第二个。。。
  • 前边的会覆盖后边的
  • 多重继承的父类必须是同级别的,不能继承 类(父类),也就是“爷爷类”
  • bases ’可以用来获取当前类的所有父类,返回的是一个元组(tuple)
class A():
    def text(self):
        print('A')

class B():
    def text(self):
        print('B')

class C(A, B):
    pass

class D(B, A):
    pass
c = C()
print(C.__bases__)
c.text()
d = D()
d.text()
# (<class '__main__.A'>, <class '__main__.B'>)
# A
# B

多态

  • 面向对象的三大特性之一
  • 多态从字面上理解就是多种形态
lis = [1, 2, 3]
name = 'python'
print(len(lis))
print(len(name))
# 3
# 6

当我们使用len()方法时,我们可以用来检查列表的长度,也可以检查字符串的长度这就是一种多态,
如果没有多态,那么我们想知道列表的长度,可以使用len()方法,
而我们想知道字符串的长度,就需要别的方法了,比如loa()方法(没有这个方法,为了举例,编的)

多态:不同子类之间调用相同的放回,产生的效果不同

class Dog():
    def __init__(self, dname):
        self.name = dname

class Person():
    def __init__(self, pname):
        self.name = pname

class play():
    def __init__(self, p_name, d_name):
        self.people = p_name
        self.dog = d_name
    def Game(self):
        print('%s play with %s'%(self.people, self.dog))

d = Dog('二哈')
p = Person('shell')
c = play(p.name, d.name)
c.Game()
# shell play with 二哈

play类中,只要传入参数就可以实现A play with B的功能,至于A&B是什么我们不需要关系,他可以是任何东西,实物,人

类中的属性和方法

class A(object):
    num = 9    
    def __int__(self):
        self._name = 'shell'
    def text(self):
        print('我是实例方法text', self)

a = A()
a.text()
A.text(a)  # a.text()就等于A.text(a)
# 我是实例方法text <__main__.A object at 0x0000018B3768C588>
# 我是实例方法text <__main__.A object at 0x0000018B3768C588>

num:

  • 类属性,直接在类中定义的属性就是类属性
  • 类属性可以通过类或类的实例访问到
  • 类属性只能通过实例对象修改,无法通过类对象修改
    self._name:
  • 实例属性,通过实例对象添加的属性属于实例属性
  • 实例属性只能通过实例属性来访问&修改,类对象无法访问&修改
    text(self):
  • 实例方法,在类中以self为第一个参数的都是实例方法
  • 实例方法再调用时,python会将调用的对象作为self传入
  • 通过类对象调用实例方法时,不会自动传入self,需要手动
class A(object):
    num = 9    
    def __int__(self):
        self._name = 'shell'
    def text(self):
        print('我是实例方法text', self)
    @classmethod
    def text2(cls):
        print('我是类方法', cls)
        print(cls.num)
a = A()
A.text2()
a.text2() #  a.text2()就等于A.text2()
# 我是类方法 <class '__main__.A'>
# 9
# 我是类方法 <class '__main__.A'>
# 9

类方法

  • 类方法的第一个参数是cls,也会被自动传递,cls就是当前类对象
  • 类方法可以通过类对象去调动,也可以通过实例对象调用
class A(object):
    num = 9    
    def __int__(self):
        self._name = 'shell'
    def text(self):
        print('我是实例方法text', self)
    @staticmethod
    def text3():
        print('我是静态方法')
        
a = A()
A.text3()
a.text3()
# 我是静态方法
# 我是静态方法

静态方法

  • 静态方法,基本上是一个和当前类无关的方法,它只是一个保存到类中的函数
  • 静态方法都是一些工具方法,和当前类无关
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值