Python基础第14讲 - 面向对象(3)

Python基础第13讲 - 面向对象(3)

一、继承的简介

1、提高了代码的复用性

2、让类与类之间产生关系,有了这关系,才有了多态

继承是面向对象的三大特性之一:继承、多态、封装

isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type()

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

object是所有类的父类,所有类都继承object

class Person:
    name = ''
    age = ''

class Doctor():

    name = ''
    age = ''

    def study(self):

        print('治疗病人')


class Soldie():
    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('狗看家')


d = Dog()

print(d)    # <__main__.Dog object at 0x01CD6050>
# run()和sleep()是Dog的父类的方法
d.run()     # 动物跑...
d.sleep()   # 动物睡觉
# home()是Dog自己的方法
d.home()    # 狗看家

# issubclass() # 检查一个类是不是另一个类的子类
print(isinstance(d,Dog))            # True
print(isinstance(d,Animal))         # True


# 如果在创建类的时候省略了父类,则默认是父类是object
# object是所有类的父类,所有类都继承object
class Person(object):

    pass

# issubclass() # 检查一个类是不是另一个类的子类
print(issubclass(Dog,Animal))       # True
print(issubclass(Dog,object))       # True
print(issubclass(Animal,object))    # True
print(issubclass(Person,object))    # True

二、方法的重写

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

2.当我们去调用一个对象的时候,会优先去当前对象寻找是否就有该方法,如果有直接调用,如果没有,则去当前对象的父类中去寻找,如果有直接调用父类中的方法,如果没有, 则去父类中的父类寻找,如果有直接调用,以此类推,指导找到object,如果依然没有就报错

'''
情况1
'''
class A(object):

    def test(self):

        print('A...')

class B(A):

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

class C(B):

    pass

c = C()
c.test()    # B...
'''
情况2
'''
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.python()  # 报错

三、super()

父类中所有的方法都会被子类继承,包括特殊方法,也可以重写特殊方法(initt)

super()可以用来获取当前类的父类,并且通过super()返回的对象,调用父类方法时不需要传递self

#定义一个动物类
class Animal:

    def __init__(self,name):

        self._name = name

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

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

    @property
    def name(self):
        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
        super().__init__(name)
        self._age = age


    def run(self):

        print('狗跑了...')

    # def sleep(self):
    #
    #     print('狗睡觉...')

    def home(self):

        print('狗看家')

    @property
    def age(self):

        return self._age

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

        self._age = age

# d = Dog()       # 报错  TypeError: __init__() missing 1 required positional argument: 'name'
d = Dog('二哈',20)
d.name = '德牧'
print(d.name,d.age)

四、多重继承

语法:类名.__bases__  :可以用来获取当前类的所有父类
在python中支持多重继承的,也就是我们可以为一个类同时指定多个父类

在开发中没有特殊情况,尽量避免使用多重继承,因为多重继承会让我们代码过于复杂,
如果多个父类中有同名的方法,则会在第一个父类中寻找,然后找第二个... 前边会覆盖后面的
class A(object):

    def test(self):

        print('A....')

class B(object):
    def test(self):

        print('B中的test方法')


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

class C(B,A):

    pass

print(A.__bases__)  # (<class 'object'>,)
print(B.__bases__)  # (<class 'object'>,)
print(C.__bases__)  # (<class '__main__.B'>, <class '__main__.A'>)
c = C()
c.test()            # B中的test方法
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

    @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('钢铁侠')

c = C()

speak2(a)
结果: 你好,葫芦娃
 刚才用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
A.count = 8
print('A ',A.count)     #  A  8
print('a ',a.count)     #  A  5
print('a ',a.name)      #  a  葫芦娃

# print('A ',A.name)
a.test()  # 实例对象在调用      # 我是test方法
A.test(a) # 类对象在调用       # 我是test方法
# a.test() 等价于 A.test(a)

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

A.test3()           #  我是test3方法........
a.test3()           #  我是test3方法........
发布了46 篇原创文章 · 获赞 4 · 访问量 1309

猜你喜欢

转载自blog.csdn.net/Yauger/article/details/102810846