基础十四:面向对象三

一、继承的简介

1.提高了代码的复用性
2.让类与类之间产生了关系,有了这个关系,才有了多态继承,是面向对象的三大特征之一

class Person():
    name = ''
    age = ''



class Doctor():
    name = ''
    age = ''

    def study(self):
        print('治病救人')


class Sldie():
    name = ''
    age = ''

    def study(self):
        print('保家卫国')

举例:
定义一个狗类
1.直接修改动物类-修改起来比较麻烦,会违反ocp原则
2.直接创建一个新类(狗)-这样比较麻烦,会出现大量重复性代码,因为使用了大量的复制粘贴
3.直接从Animal类中继承他的属性和方法

#定义一个动物类
class Animal:
    def run(self):
        print('动物跑..。。')

    def sleep(self):
        print('动物睡觉.。。')


a = Animal()
a.run() #动物跑..。。


# # 定义类时,可以在类名后面加上括号,括号中指定的是当前类的父类(超类,基类,super)
class Dog(Animal):
    def run(self):
        print('狗跑..。。')
    #
    # def sleep(self):
    #     print('狗睡觉.。。')
    #
    def home(self):
        print('狗看家.。。')
    pass

d = Dog()
# print(d) #<__main__.Dog object at 0x000001A6BE4F4148>
#
d.run() #狗跑..。。
# d.sleep() #动物睡觉.。。

r = isinstance(d,Dog)
print(r) #True
s = isinstance(d,Animal)
print(s) #True
若創建类的时候省略了父类,则默认父类是object
object是所有类的父类,所有类都继承了object
class Person():

    pass

# issubclass()--检查一个类是不是另一个类的子类

print(issubclass(Dog,Animal)) #True
print(issubclass(Dog,object)) #True
print(issubclass(Animal,object)) #True
print(issubclass(Person,object)) #True

二、方法的重写

若在子类中有和父类同名的方法,通过子类的实例去调用方法时,会调用子类的方法,而非父类的方法
这就是方法的重写(覆盖)

当我们去调用一个对象的时候
会优先调用当前对象的方法,若当前对象中没有这个方法,则会去父类中寻找,若其父类中
也没有,则会去父类的父类寻找,若无,则会逐级向上,直到object中去,若object也没有,会报错

class A(object):
    def test(self):
        print('A....')


class B(A):
    def test(self):
        print('B....')

class C(B):
    def test(self):
        print('C....')

c=C()
c.test() #C....
c.sty() #AttributeError: 'C' object has no attribute 'sty'

三、super()

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

#定义一个动物类
class Animal:
    def __init__(self,name):
        self._name = name

    def run(self):
        print('动物跑..。。')

    def sleep(self):
        print('动物睡觉.。。')

    @property
    def name(self):
        # print('property执行')
        return self._name

    @name.setter
    def name(self,name):
        self._name = name

# 希望能够直接调用父类的__init__来初始化父类中的属性
# super可以用了获取当前的父类
# 并且通过super()返回的对象,调用父类方法时不需要写self
class Dog(Animal):

    def __init__(self,name,age):
        # 希望能够直接调用父类的__init__
        # self._name = name
        # Animal.__init__(self,name)
        super().__init__(name)
        self._age = age


    def run(self):
        print('狗跑..。。')
    #
    # def sleep(self):
    #     print('狗睡觉.。。')
    #
    def home(self):
        print('狗看家.。。')

    @property
    def age(self):
        # print('property执行')
        return self._age

    @age.setter
    def age(self, age):
        self._age = age


# e = Dog() #TypeError: __init__() missing 1 required positional argument: 'name'

#子类未重写init方法之前,即注释方法def __init__(self,name,age):
# e = Dog('蛇精病')
# print(e.name) #蛇精病
# e.name = '二哈'
# print(e.name) #二哈

#子类未重写init方法之后
e = Dog('long',3)
print(e.name,e.age) #long 3

四、多重继承

语法:类名.__bases__可以用了获取当前类的所有父类
在Python中是支持多重继承的,也就是我们可以为一个类同时指定多个父类
在开发中没有特殊情况,尽量避免使用多重继承,因为多重继承会让我们代码过于复杂
如果多个父类中有同名的方法,则会在第一个父类中寻找,然后找第二个…(父类顺序以写入的顺序为准)
前边会覆盖后面的

class A(object):
    def test(self):
        print('A....')


class B(object):
    def test2(self):
        print('B....')

class C(A,B):
    pass

print(C.__bases__) #(<class '__main__.A'>, <class '__main__.B'>)-元组
print(A.__bases__) #(<class 'object'>,)-元组
print(B.__base__) #<class 'object'>

c = C()
c.test() #A....
c.test2() #B....

五、多态

面向对象的三大特征之一
熊(黑熊、棕熊、北极熊…)

一个对象可以以不同的形态去呈现

# 定义一个类
class A:

    def __init__(self,name):

        self._name = name

    @property
    def name(self):

        return self._name

    @name.setter
    def name(self,name):

        self._name = name


class B:

    def __init__(self,name):

        self._name = name

    # def __len__(self):
    #
    #     return 5

    @property
    def name(self):

        return self._name

    @name.setter
    def name(self,name):

        self._name = name

class C:
    pass

# 定义一个函数
def speak(obj):

    print('你好 %s'%obj.name)

# 在speak2这个函数中做了一个类型检查,也就是只有obj是A类型的对象的时候,才可以正常使用,其他类型的对象无法使用该函数,这个函数其实就违反了多态
# 违反了多态的函数,只适用于一种类型的对象,无法处理其他类型的对象,这样导致函数的适用性非常差
def speak2(obj):
    # 类型检查
    if isinstance(obj, A):
        print('你好 %s' % obj.name)

a = A('葫芦娃')

b = B('钢铁侠')
# print(len(b)) #TypeError: object of type 'B' has no len()
c = C()

speak(b) #你好 钢铁侠

speak2(a) ##你好 葫芦娃
speak2(b) #因为speak2中设置了对象的检查,只有A类型的可以输出,所以此时没有输出


# len()
lst = [1,2,3]
s = 'python'
print(len(lst)) #3
print(len(s)) #6

# 刚才用len()函数来检查不同对象类型的长度其实就是面向对象的特征之一
# 之所有len()这个函数能获取长度,是因为这些对象中具有一个特殊方法__len__
# 换句话说只要对象中有__len__特殊方法,就可以通过len()方法来获取它的长度


# 面向对象的三大特征
# 封装 确保对象中的数据更安全
# 继承 保证了对象的可扩展性
# 多态 保证了程序的灵活性

# len()
lst = [1,2,3]
s = 'python'
print(len(lst)) #3
print(len(s)) #6
 刚才用len()函数来检查不同对象类型的长度其实就是面向对象的特征之一
	之所以len()这个函数能获取长度,是因为这些对象中具有一个特殊方法__len__
 	换句话说只要对象中有__len__特殊方法,就可以通过len()方法来获取它的长度

六、 类中的属性和方法

类属性:
	实例属性
类方法:
	实例方法
	静态方法
class A(object):

    # 类属性 直接在类中定义的属性就是类属性
    # 类属性可以通过类或类的实例访问到
    # 类属性只能通过类对象来修改,无法通过实例对象来修改
    count = 0

    def __init__(self):
        # 实例属性,通过实例对象添加的属性属于实例属性
        # 实例属性只能通过实例属性来访问和修改,类对象无法访问和修改
        self.name = '葫芦娃'
    # 实例方法
    # 在类中定义,以self为第一个参数都是实例方法
    # 实例方法在调用时,Python会将调用对象作为self传入
    # 通过类对象调用时,不会自动传self,必须手动传self
    def test(self):

        print('我是test方法')

    # 类方法
    # 类方法的第一个参数是cls,也会被自动传递,cls就是当前的类对象
    # 类方法可以通过类去调用,也可以通过实例调用
    @classmethod
    def test2(cls):
        print('我是test2方法.........',cls)
        print(cls.count)
    # 静态方法
    # 静态方法,基本上是一个和当前类无关的方法,它只是一个保存到当前类中的函数
    # 静态方法一般都是些工具方法,和当前类无关
    @staticmethod
    def test3():

        print('我是test3方法........')


a = A()
# 实例属性 通过实例对象添加的属性属于实例属性
a.count = 5
print('A ',A.count) # A  0
print('a ',a.count) # a  5

A.count = 8
print('A ',A.count) # A  8
print('a ',a.count) # a  5

print('a ',a.name) # a  葫芦娃
# print('A ',A.name) # AttributeError: type object 'A' has no attribute 'name'

a.test() # 实例对象在调用--我是test方法
# A.test() # TypeError: test() missing 1 required positional argument: 'self'
A.test(2) #类对象在调用-我是test方法
# a.test() 等价于 A.test(a)

A.test2() #我是test2方法......... <class '__main__.A'>   8
a.test2() #我是test2方法......... <class '__main__.A'>   8
# A.test2() 等价于 a.test2()

A.test3() #我是test3方法........
a.test3() #我是test3方法........
# 类属性
# 实例属性
# 类方法
# 实例方法
# 静态方法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值