Python(面向对象)——继承、重写、super()、多重继承、多态、属性和方法

继承的简介

1、提高代码复用性
2、让类与类之间产生了关系,有了这个关系,才有了多态
3、继承也是面向对象的三大特征之一
换句话说:没有继承哪里来的多态。
注意:在定义类时后面加上括号,括号内中指定的是当前类的父类(超类、基类、super)
在创建类的时候,如果省略了父类,那么Python会自动添加一个类(object)类 。所有类都继承object,object是所有类的父类

#创建一个类
class Person():

    #创建一个方法:
    def sleep(self):
        print('我在睡觉')

    #在创建一个方法
    def run(self):
        print('我在跑步')

#创建一个类,并继承他的类
class student(Person):     #定义一个类让他继承他的父类(在定义类时,可以在类括号加上括号,括号中的内容指定的类是当前类的父类)
    pass

#创建一个实例对象
p1 = student()
p1.run()
p1.sleep()

运行结果:

我在跑步
我在睡觉

isinstance检查一个类是否是另一个类的实例
issubclass检查一个类是否是另一个类的子类

#检查一个类是否是另一个类的实例
result = isinstance(p1,student)
result1 = isinstance(p1,Person)
print(result)
print(result1)

#检查一个类是否是另一个类的子类
result3 = issubclass(student,Person)
print(result3)
result4 = issubclass(Person,object)
print(result4)

运行结果:

True
True
True
True

方法重写

当子类中存在与父类重名的方法,通过子类的实例来调用方法时,会调用子类的方法而不是父类的方法,这个特点称之为方法的重写(覆盖 override)

#创建一个类
class Person(object):   #不写object也可以,会自动继承object方法

    #创建一个方法
    def speak(self):
        print('这个是Person的方法')

    #创建第二个方法
    def run(self):
        print('这个是Person在跑')

#创建第二个类,并继承Person类
class teacher(Person):

    #创建一个teacher方法
    def speak(self):
        print('这个是teacher的方法')

p1 = teacher()
p1.speak()
p1.run()

运行结果:

这个是teacher的方法
这个是Person在跑

方法重写:(会优先去当前对象中寻找方法,如果有直接调用该方法。如果没有,则去当前定义的父类中寻找,如果有将直接调用。如果没有,则会去父类的父类中寻找,以此类推直到找到object为止,如果有则调用,没有则报错)

class A(object):

    def speak(self):
        print('a方法')

class B(A):
    def speak(self):
        print('B方法')

class C(B):
    pass

p = C()
p.speak()

运行结果:

B方法

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

#创建一个类
class Person():
    def run(self):
        print('人在跑')

    def sleep(self):
        print('人在睡觉')

    #创建一个特殊方法,并设置属性
    def __init__(self,name):
        #封装
        self._name = name

    @property  #装饰器getter方法(查看name属性值)
    def name(self):
        return self._name
    @name.setter  #装饰器setter方法(修改name属性值)
    def name(self,name):
        self._name = name

class teacher(Person):

    
    def run(self):
        print('老师在跑')

    def sleep(self):
        print('老师在睡觉')

p1 = teacher('大师')
p1.name = '程序员'
print(p1.name)


运行结果:

程序员

super() 可以获得当前类的父类

# 创建一个类
class Person():
    def __init__(self, name):
        self._name = name

    def speak(self):
        print('%s在跑' % self._name)

    @property
    def name(self):
        return self._name

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


# 创建第二个类
class students(Person):
    def __init__(self, name, age):
        self._name = name
        self._age = age
        # super()这个方法就是在创建类时,类的父类是谁,就调用谁
        super().__init__(name)  # 让子类students调用父类Person的方法

    def speak_age(self):
        print('我的年龄是%s' % self._age)

    @property
    def age(self):
        return self._age

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


a = students('Python程序员',18)
a.speak()
a.speak_age()
print(a.name)
print(a.age)


运行结果:

Python程序员在跑
我的年龄是18
Python程序员
18

总结:
super()的好处:super()方法的漂亮之处在于,你不需要定义子类的构造器时,明确的指定子类的基类并显式的调用,即不明确的提供父类。这样做的好处就是,如果你改变了继承的父类,你只需要改继承的父类,而不需要在大量代码中去寻找那个要修改的基类,另一方面,代码的可移植性和重用性也更高

多重继承

语法用法:类名.__bases__

__bases__用来获取当前定义的类的父类

在Python中是支持多重继承的,也就是我们可以为一个类同时指定多个父类

class A():
    pass

class B(A):
    pass

class C(B,A):   #注意:继承可以单继承,也可以多继承
    pass


print(C.__bases__)

运行结果:

(<class '__main__.B'>, <class '__main__.A'>)

在开发过程中没有特殊情况,尽量避免使用多重继承,因为多重继承会我们的代码的过于复杂,如果多个父类中有同名的方法,则会在第一个父类中寻找,如果有则调用,没有则去第二个父类中寻找,以此类推.(当父类中有同名的方法时,则前面的父类会覆盖后面的父类方法)

class A(object):
    def speak(self):
        print('我是A方法')

class B(object):
    def speak1(self):
        print('我是B方法')

class C(B,A):   #先去类中定义的第一个父类中寻找,如果有,则使用。如果没有,则去第二个父类中寻找,以此类推
    pass


c = C()
c.speak()

运行结果:

我是A方法

多态
多态是面向对象的三大特征之一
一个对象可以以不同的形态去呈现

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 __len__(self):
        return 10

    def __init__(self, name):
        self._name = name

    @property
    def name(self):
        return self._name

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


a =A('光头强')
b =B('大耳朵图图')
def speak(obj):
    print('你好我是%s'%obj.name)

def speak1(obj):
    #做类型检查
    #违反了多态的函数只适用于一种类型的对象,无法处理其他类型的对象,这样会导致函数的实用性很差
    #通用性比较差,但他的好处就是不容易出错
    if isinstance(a,A):
        print('经过检查%s是A的属性'%obj.name)

# speak1(a)
# speak(a)
# print(len(b))

属性和方法

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

class math():
    count = 0     # 定义一个类属性,类属性只能通过类修改,无法通过实例对象修改

a = math()  # 创建一个实例对象
print(a.count)  # 通过实例来读取
print(math.count)  # 通过类属性来读取


math.count = 20    # 当通过类属性来修改类值之后,实例对象的值也会跟着改变
# print(a.count)   #(当通过实例对象来修改属性的时候,修改的是属性值,并不是类的属性值,类属性值不会受到影响)
print(a.count)
print(math.count)

运行结果:

0
0
20
20

什么是实例方法?
实例对象就是实例方法在类中直接定义的
在类中定义的,以self为参数的方法都是实例方法
实例方法在调用时,Python会将调用的对象作为self传入
当通过类调用时,不会自己传入self
实例属性
实例属性通过实例对象添加的属性叫做实例属性
实例属性只能通过实例对象来访问和修改,对象无法访问和修改

class Person():
    # 这个特殊方法也是实例方法,因为他只能通过实例对象来访问
    def __init__(self,name):
        self._name = name

    def speak(self):   # 在类中以self为参数的都是实例方法
        print('%s正在讲话'%self._name)

a = Person('Python程序员')
a.speak()
Person.speak(a)   #通过类调用时,不会自动传入self

运行结果:

Python程序员正在讲话
Python程序员正在讲话

类方法
通过@classmethod来修饰的方法是类方法.(注意:类方法可以操控类的属性)
类方法的第一个参数是cls,会自己传递,cls就是当前类的类对象.类方法和实例方法的区别,实例方法第一个参数是self,而类方法第一个传递的是cls.
类方法也可以通过实例方法来调用

class Person():
    count = 10
    # 这个特殊方法也是实例方法,因为他只能通过实例对象来访问
    def __init__(self,name):
        self._name = name

    def speak(self):   # 在类中以self为参数的都是实例方法
        print('%s正在讲话'%self._name)

    @classmethod    #类方法
    def text(cls):   #类方法默认传递cls
        print('我是Person当中的类方法')
        print(cls.count)

a = Person('Python程序员')
Person.text()   #类方法通过类来调用则不需要传递参数
a.text()    #类方法也可以通过实例对象来调用
            #总结:类方法和实例方法一个本质上的区别就是:类方法第一个默认传参是cla,而实例方法是self

运行结果:

我是Person当中的类方法
10
我是Person当中的类方法
10

静态方法
在类中内部使用@staticmethod来修饰的方法属于静态方法,静态方法不需要指定的任何默认的参数,静态方法可以通过类和实例去调用
(静态方法的好处是:可以通过类去调用该方法,让编译器不能直接调用,相当于是保存到类中的一个函数)

class Person():
    count = 10
    # 这个特殊方法也是实例方法,因为他只能通过实例对象来访问
    def __init__(self,name):
        self._name = name

    def speak(self):   # 在类中以self为参数的都是实例方法
        print('%s正在讲话'%self._name)

    @classmethod    #类方法
    def text(cls):   #类方法默认传递cls
        print('我是Person当中的类方法')
        print(cls.count)
    #静态方法
    @staticmethod
    def text2():   #静态方法里面不需要传递任何参数,静态方法可以通过类和实例去调用
        print('这个是Person当中的类方法')

a = Person('Python程序员')
# Person.text()   #类方法通过类来调用则不需要传递参数
# a.text()    #类方法也可以通过实例对象来调用
#             #总结:类方法和实例方法一个本质上的区别就是:类方法第一个默认传参是cla,而实例方法是self
Person.text2()
a.text2()

运行结果:

这个是Person当中的类方法
这个是Person当中的类方法
发布了54 篇原创文章 · 获赞 26 · 访问量 6196

猜你喜欢

转载自blog.csdn.net/qq_37662827/article/details/102791098