Python零基础之面向对象(继承,方法的重写,super(),多重继承,多态,属性和方法)

继承

  • 什么是继承?
    继承是一种创建新的类的方式,新创建的叫子类,继承的叫父类、超类、基类。
  • 特点:子类可以使用父类的属性(特征、技能)
  • 继承是类与类之间的关系
  • 为什么要继承?
    减少代码冗余、提高重用性
  • 可以用 isinstance() 或 issubclass() 验证实例或类的从属关系
# 继承
# 1.让类之间产生关系,从而实现了多态
# 2.提高了代码复用性
# 3.在创建类的时候,如果省略了父类,则默认父类为object
# 4.object时所有类的父类

class Animal:

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

    def run(self):
        print('动物会跑')

# class Dog:
#
#     def sleep(self):
#         print('狗会睡觉')
#
#     def run(self):
#         print('狗会跑')
#
#     def speak(self):
#         print('狗会旺旺')

# 想定义一个狗类

# 第一个思路:直接改Animals类,添加狗独有的功能
# 这样修改很麻烦,会破坏了OCP原则

# 第二个思路:创建一个新的狗类
# 会出现大量的复制粘贴,修改起来也比较繁琐

# 第三个类,利用类的继承
# 在定义类的时候可以在类名后的括号中指定当前类的父类(超类,基类)
class Dog(Animal):
    def speak(self):
        print('狗会旺旺')
    def run(self):
        print('狗会跑')

d = Dog()
d.sleep()
d.run()
d.speak()
# d既时Dog的实例也是Animals的实例
# 检查一个实例是不是某个类的实例
r = isinstance(d,Dog)
print(r)
r = isinstance(d,Animal)
print(r)
# 检查某个类是不是另一个类的子类
r = issubclass(Dog,Animal)
print(r)
# 检查object是否为任意类的父类
r = issubclass(Animal,object)
print(r)
r = issubclass(Dog,object)
print(r)
r = issubclass(int,object)
print(r)
# 如果子类和父类出现同名方法,则先找子类,子类没有再找父类
d.run()

方法的重写

  • 如果子类和父类出现同名方法,则先找子类,子类有则调用子类方法
  • 如果子类没有,再找父类,调用父类方法
class A(object):
    def test(self):
        print('A...')

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

class C(B):
    pass

c = C()
c.test()

super()

  • super()用来动态获取当前父类
  • 可以用来避免子类属性覆盖父类属性
  • 子类中只定义独有属性即可
  • super()不需要传递self
class Animal:

    def __init__(self,name):

        self.name = name

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

    def run(self):
        print('动物会跑')

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

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

# 子类有而父类没有的内容,可以添加进来
# 但是要避免把父类的属性给覆盖掉
class Dog(Animal):

    def __init__(self,name,age):

        # self._name = name
        # 希望调用父类的__init__
        # Animal.__init__(self,name)
        # 但是最好不要把父类写死
        # super可以用来获取当前类的父类
        # super()初始化父类,不需要传递self
        super().__init__(name)
        # 子类独有的属性再自己写
        self._age = age

    def sleep(self):
        print('狗会睡觉')

    def run(self):
        print('狗会跑')

    def speak(self):
        print('狗会旺旺')

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

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

d = Dog('大狼狗',6)

print(d.name,d.age)

多重继承

  • Python中时可以多继承的,我们可以为一个类指定多个父类
  • 两个父类之间不能有继承关系
  • 类名.bases 可以获取当前类的所有父类
  • 注意: 尽量少使用多重继承
class A(object):
    def test1(self):
        print('A...')

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

class C(A,B):
    pass

# 类名.__bases__ 可以获取当前类的所有父类
print(C.__bases__)

c = C()
# 当父类中有同名的方法,则按照继承的顺序进行寻找
# 即如果改成class C(B,A): 则调用的结果会不同
c.test1()
c.test2()

多态

  • 多态是面向对象三大特性之一
  • 一个对象也是可以有不同的形态取呈现
  • 一个函数可以处理多个对象就是多态的一种体现
  • 体现了函数的灵活性
  • 对扩展开放(Open for extension):允许子类重写方法函数
  • 对修改封闭(Closed for modification):不重写,直接继承父类方法函数

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

a = A('葫芦娃')
b = B('钢铁侠')
# a其实是一个__main__.A object
print(a)
# 输出了字符串,没有property之前其实是a.name()
print(a.name)

# 定义一个函数

def speak(obj):

    print('好好复习%s'%obj.name)
# 传入给speak()函数的对象a实际上是__main__.A object,用字符串格式化依然可以进行a.name的传入
# 这说明了函数的灵活性,函数的对象可以是多种类型,并不局限于字符串等常见格式
speak(a)


# speak2这个函数违反了多态
# 只能处理一个类型的对象,函数适用性差
def speak2(obj):

    if isinstance(obj,A):
        print('好好复习%s'%obj.name)
    else:
        print('不是speak2()想要的对象')

speak2(a)
speak2(b)

属性和方法

  • 类属性: 直接在类中定义的属性
  • 类属性可以通过类和该类的实例进行访问
  • 类中的属性只能通过类对象进行修改,无法通过实例对象来修改
  • 修改类中属性相当于修改默认值,不会影响创建过的实例对象的属性,但是会影响新创建的实例对象的属性
  • 实例对象先找自己的实例属性,没有了才找类属性
  • 以self为第一个参数的方法都是实例方法
  • 代码示例:
class A(object):

    count = 0

    def __init__(self):
        # 这个反而是实例属性
        self.name = '葫芦娃'


# print(A.count)
#
a = A()
# print(a.count)
# a.count = 10
# print('A:',A.count)
# print('a:',a.count)
# A.count = 20
# print('A:',A.count)
# print('a:',a.count)
# self是实例属性
print('a', a.name)
# AttributeError: type object 'A' has no attribute 'name'
# print('A',A.name)
  • 类方法: 在类的内部使用@classmethod来修饰的方法属于类方法
    • 首先形式上的区别,实例方法隐含的参数为类实例self,而类方法隐含的参数为类本身cls。 静态方法无隐含参数,主要为了类实例也可以直接调用静态方法。
    • 逻辑上,类方法被类调用,实例方法被实例调用,静态方法两者都能调用。主要区别在于参数传递上的区别,实例方法悄悄传递的是self引用作为参数,而类方法悄悄传递的是cls引用作为参数。
  • 注意:
    • 当通过实例对象调用函数可以自动传入self
    • 当通过类对象调用函数不会自动传入self,需要手动添加实例对象名, 但通过@classmethod装饰的方法可以不用传入实例名
  • 静态方法: 在类中以@staticmethod修饰的方法
    • 静态方法不用传入参数
    • 静态方法可以通过类调用也可以通过实例调用
# !/usr/bin/python
# Filename: 模块.py
# Data    : 2020/06/17
# Author  : --king--
# ctrl+alt+L自动加空格格式化


class A(object):
    # 类属性: 直接在类中定义的属性
    # 类属性可以通过类和该类的实例进行访问
    count = 0

    def __init__(self):
        # 这个反而是实例属性
        self.name = '葫芦娃'

    def text(self):
        print('这是self方法:',self)

    # 类方法: 在类的内部使用@classmethod来修饰的方法属于类方法
    @classmethod
    def text2(cls):# cls就代表类名和self一样自动传入
        print('这是test2方法:',cls)
        print(cls.count)
	# 静态方法:再累内部使用@staticmethod来修饰的方法 
    @staticmethod
    def text3():
        print('这是text3方法')

a = A()
# 类方法可以通过类对象和实例对象调用
A.text2()
a.text2()
# 静态方法可以不传入函数直接调用
# 他本身与类无关,只是用来保存一个功能函数
A.text3()
a.text3()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

kingx3

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

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

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

打赏作者

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

抵扣说明:

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

余额充值