类的继承与多态--(python16)

1. 类的继承

1.1 继承的实现

继承:子类继承父类的属性和方法
当子类对象去调用方法时,会先在子类中去查找 方法,如果有,那么就执行,如果没有找到,父类中去查找 该方法,如果找到执行找不到再到上一级类中去查找 直到找到object类,如果还没有那么就报错

格式:

class  子类名(父类名称,...):
		pass
'''
子类继承父类的属性和方法
'''
class Father(object):
    def __init__(self):
        self.name = '电话'

    def call(self,number):
        print(f'正在给谁打电话{number}')
class Son(Father):
    def crema(self,name):
        print(f'给谁照相:{name}')

s = Son()
print(s.name)
s.call(123)
s.crema("tom")

1.2 子类不能直接使用父类的私有属性和方法

只能通过父类中的共有的方法来间接的进行使用

'''
子类继承父类的属性和方法
'''
class Father(object):
    def __init__(self):
        self.name = '电话'
        self.__money = 99
    def __show(self):
        print('父类的私有方法')
    def diaplay(self):
        print('父类的共有方法')
        #想访问父类中私有方法是能通过父类的共有方法进行间接的使用
        self.__show()
    def get_money(self):
        return self.__money

class Son(Father):
    def play(self):
        print('子类的共有方法')
        # 通过继承可以使用父类的共有方法
        self.diaplay()
s = Son()
print(s.name)
# 私有属性不能访问
# print(s,money)
s.play()
print(s.get_money())

如果想使用父类中的私有属性和私有方法,那么就需要在父类中,为这些私有的属性和方法,提供相应的公有的接口方法来间接访问

1.3 子类初始化父类中的属性

父类名.方法名(self)

'''
子类初始父类的属性
类名.init方法
'''
class Father(object):
    def __init__(self,name):
        self.name = name

class Son(Father):
    # 子类在定义了init犯法之后,执行的时候就不会继承调用父类中的init方法,就不会绑定父类中的属性
    # 这个时候就需要我们手动的调用执行父类的int方法
    # 注意这个时候就需要写入self这个参数
    def __init__(self,name,age):
        Father.__init__(self,name)
        self.age = age


s = Son('tom',12)
print(s.name)
print(s.age)

1.4 子类重写父类的方法

class Father(object):
    def show(self):
        print('我是一个老中医哦')

class Son(Father):
    def show(self):
        # 要想执行父类中的方法
        Father.show(self)
        print('我是一个西医')

# 重写父类中的方法之后,调用的时候就不会执行父类中的方法
s = Son()
s.show()

1.5 多层继承和多继承

多层继承:纵向

'''
多层继承是纵向的
'''
class A(object):
    def a(self):
        print('a ...Run')

class B(A):
    def b(self):
        print('b ...Run')

class C(B):
    def c(self):
        print('c...Run')

class D(C):
    def d(self):
        print('d ...Run')

# 测试
d = D()
d.a()
d.d()
d.c()
d.d()

多层继承属性的初始化问题:

'''
多层继承是纵向的
'''
class A(object):
    def __init__(self,a):
        self.a = a

class B(A):
    def __init__(self,a,b):
        A.__init__(self,a)
        self.b = b

class C(B):
   def __init__(self,a,b,c):
       B.__init__(self,a,b)
       self.c = c

class D(C):
    def __init__(self,a,b,c,d):
        C.__init__(self,a,b,c)
        self.d = d
# 测试
d = D(1,2,3,4)
print(d.a)
print(d.b)
print(d.c)
print(d.d)

print(d.__dict__)
print(D.__dict__)

多继承:

class Father(object):
    def show_fa(self):
        print('i am father ')
class Mother(object):
    def show_mo(self):
        print('mother')
class Som(Father,Mother):
    def show(self):
        print('son')

# 测试
s = Som()
s.show_fa()
s.show_mo()

多继承出现的父类多次进行初始化的问题:

'''
当我父类还有一个共同的父类的时候,就会出现重复执行的问题

共同的父类会被初始化多次

'''
class Person(object):
    def __init__(self,p):
        print('person run')
        self.p =p

class Father(Person):
    def __init__(self,p,name):
        print('father run...')
        Person.__init__(self,p)
        self.name =name

class Mother(Person):
    def __init__(self,p,age):
        print('mother run...')
        Person.__init__(self, p)
        self.age= age

class Son(Father,Mother):
    def __init__(self,p,name,age,a):
        Father.__init__(self,p,name)
        Mother.__init__(self,p,age)
        self.a = a

s = Son(23,'tom',12,23)
print(s.p)
print(s.name)
print(s.age)
print(s.a)
print(Son.__mro__)

解决办法:
super()的应用
super(类名,self)的方式

'''
使用的是super(类名,self)的方式
'''

class Person(object):
    def __init__(self,aaa):
        print('Person Init ...')
        self.aaa = aaa

class Father(Person):
    def __init__(self,name,*args):
        super(Father, self).__init__(*args)
        print('Father Init ...')
        self.name = name


class Mother(Person):
    def __init__(self,age,*args):
        super(Mother, self).__init__(*args)
        print('Mother Init ...')
        self.age = age


class Son(Father, Mother):
    def __init__(self,aaa, name,age, gender):
        # 参数二是当前类的实例对象
        # 参数一是当前类名
        # 在参数二对象的所属类的mro关系 中找参数一的下一个类进行实始化
        super(Son, self).__init__(name,age,aaa)
        print('Son Init ...')
        self.gender = gender

# 测试
s = Son(1,2,3,4)
print(s.aaa)
print(s.name)
print(s.age)
print(s.gender)
print(Son.__mro__)

super简化

class Person(object):
    def __init__(self,p):
        self.p = p

class Father(Person):
    def __init__(self,name,*args):
        super().__init__(*args)
        self.name = name
class Mother(Person):
    def __init__(self,age,*args):
        super().__init__(*args)
        self.age = age

class Son(Father,Mother):
    def __init__(self,p,name,age,h):
        super().__init__(name,age,p)
        self.h = h
s =Son(1,'tom',23,4)
print(s.p)
print(s.name)
print(s.age)
print(s.h)
print(Son.__mro__)

1.6 mro

类名.mro 得到了一个元组,元组中的元素是当前类在继承关系上的一个顺序

类继承的顺序的书写会影响mro的执行顺序,他是一个元组,不会改变

class A(object):
    pass
class B(A):
    pass
class C(A):
    pass
# (<class '__main__.D'>,
# <class '__main__.B'>,
# <class '__main__.C'>,
# <class '__main__.A'>,
# <class 'object'>)
# class D(B,C):
#     pass

class D(C,B):
    pass
# (<class '__main__.D'>,
# <class '__main__.C'>,
# <class '__main__.B'>,
# <class '__main__.A'>,
# <class 'object'>)

print(D.__mro__)

方法也会根据mro来决定

class A(object):
    def show(self):
        print('a')
class B(A):
    def show(self):
        print('b')
class C(A):
    def show(self):
        print('c')

class D(C,B):
    def show(self):
        # 注意使用 类名.方法,和super的区别,
        # super 不用写self
        # B.show(self)
        super().show()
        print('d')

d = D()
d.show()

print(D.__mro__)

2. 多态

当调用一个方法名的时候,得到的结果不同
在一般的面向对象语言中,多态是由继承来实现的
但是在python中,python,天生具有多态性

class Father(object):
    def cure(self):
        print('只会古老的中医疗法')

class Son(Father):
    def cure(self):
        print('中西结合')

class Dog(object):
    def bark(self):
        print('won won...')

class Person(object):
    def look(self,docter):
        docter.cure()

p = Person()
p.look(Son())
p.look(Father())
# 没有这个方法就不会
# p.look(Dog()) AttributeError: 'Dog' object has no attribute 'cure'


3. 其他的补充

3.1 实例的属性和实例的方法

class A(object):
    # 实例属性
    def __init__(self,a):
        self.a = a
    #  实例方法
    def show(self):
        print('aaa')

# 调用
a = A(12)
# 查看实例属性
print(a.a)
# 使用实例方法
a.show()

# 类名不能调用实例属性和方法
# A.show()
# 因为类存在不一定有实例对象,实例的属性方法,只有实例可以调用

3.2 类的属性和类对象

class Room(object):
    # 用于实现数据间的共享
    name = '901'

    # 实例方法:
    def show(self):
        print('实例方法中访问类的属性')
        print(Room.name)

# 可以直接通过类名访问
print(Room.name)

# 实例也可以访问
c1 = Room()
print(c1.name)
c2 = Room()
print(c2.name)

# 更改时候通过类名更改才能使全局改变,使用实例只是把实例分配一个新的值的引用,并不会改变name原有的值
c1.name = '903'
print(c1.name)
print(c2.name)


Room.name = 905
print(c1.name)
print(c2.name)


c1.show()

3.3 属性和方法的保存位置dict魔法函数

class Dog(object):
    def __init__(self,name):
        self.name = name
        self.__age = 1

    def public_method(self):
        print('public')

    def __private_metod(self):
        print('private')

d = Dog('tom')
jack = Dog('Jack')

print(d.__dict__)
print(jack.__dict__)
print(Dog.__dict__)

在这里插入图片描述

3.4 类方法和静态方法(大多数在工具类中使用)

类方法:@classmethod

'''
@classmethod修饰
当我们不需要实例化对象的时候
'''

class Test(object):
    # classmethod是一个装饰器,他在执行代码的时候,会自动的把类类的对子昂参数传递到cls
    @classmethod
    def sum(cls,*args):
        m = 0
        for i in args:
            m+=i
        print(m)
    # 不加@classmethod
    def show(cls):
        print('classmethod')

Test.sum(1,2,3,4)
Test.show(Test)

静态方法:@staticmethod

class Util(object):
    @staticmethod
    def encode(data,code):
        print(f'数据{data}进行了编码{code}')
    @staticmethod
    def decode(data,code):
        print(f'数据{data}进行了{code}解码')

Util.decode('123','utf-8')
u = Util()
u.encode('456','GBK')

总结:
1.实例方法:必须通过实例对象调用执行,第一个参数是调用方法的实例
2.类方法:但不需要产生实例的时候,类方法可以直接使用类名来进行调用,第一个参数cls,用来接收当前类对象,可以进行类方法之间的数据共享
3.静态方法:同类方法,但是今天方法不接受任何默认的参数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长安有故里y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值