Python类【继承、扩展、重写、覆盖、多态】

零.前言:

本文适合对Python有浅浅了解的读者,并不能作为Python入门使用。

一.Python中类的属性、方法

在Python中有变量,有函数,例如下方:

def IAmAFunction():
    print("I am a function")

IAmVariable = 250

我们创建了一个名为“IAmVariable”的变量跟一个名为“IAmAFunction”的函数。

当然,在中也有变量跟函数,不过在中的变量函数分别叫做:“属性”、“方法”。

例如:

class Sample():
    def __init__(self):
        self.name = "Pig"
    def Print_MyName(self):
        print(self.name)

我们创建了一个名为“Sample”的类,并且在这个类中创建了两个方法:“__init__()”、“Print_MyName”,一个属性:“self.name”。

对于类中的属性方法,同C++一样也分为:“保护”、“私有”、“公共”三大类。

不过在本章我们并不对这三类展开论述,感兴趣的读者可以移步作者的另一篇文章

二.__init__()方法:

所有的类都有一个内置的__init__()方法,它在创建一个类对象的时候“第一个被自动执行”。

每次创建一个新的类对象的时候,都会调用一次类的__init__()方法。

通过__init__()函数,我们可以在创建一个类对象的时候通过传参的方式人为的改变这个类对象的一些属性。

例如:

class Pig():
    def __init__(self,name,age,weight):
        self.name = name
        self.age = age
        self.weight = weight
    
    def Pig_Information(self):
        print(f"本猪的名字是{self.name},芳龄是{self.age},还有俺的吨位是{self.weight}")

pig = Pig("小芳","19","200kg")
pig.Pig_Information()

我们创建了一个Pig类,并且创建了一个pig对象pig对象在创建的时候传入了参数:“小芳”、“19”、“200kg”,这三个参数将分别通过__init__方法赋值给:“self.name”、“self.age”、“self.weight”三个属性。

最后我们调用Pig_Informaton()方法输出pig对象的各个属性。

三.self参数

self参数表示:“对当前类对象的引用,用于访问该类对象”。

PS:“它不必被命名为self,您可以随意改名并且调用它,但它必须是类方法的首个参数!!

例如,我们使用“me”和“myself”来代替self

class Pig():
    def __init__(myself,name,age,weight):
        myself.name = name
        myself.age = age
        myself.weight = weight

    def Pig_Information(me):
        print(f"本猪的名字是{me.name},芳龄是{me.age},还有俺的吨位是{me.weight}")

pig = Pig("小芳","19","200kg")
pig.Pig_Information()

运行结果:

 可以发现,self仅仅表示对某一个类对象的引用,为什么要用self?答案显而易见:

“例如有两个Pig()类对象,分别名为p1p2p1p2都有公共的类属性name”。

那么问题来了,如果没有self引用表示某个类对象,在类方法中使用的时候,程序又怎么知道使用的是p1还是p2name属性呢?所以需要self来表示是“p1”还是“p2”。

四.继承:子类继承父类

4.1继承的含义:

子类继承父类的所有属性和方法。

4.2继承方法

一般而言,使用类继承的时候,我们有如下操作:

父类不做任何操作。

子类在创建子类时将父类作为参数传入。

4.3不同的继承方式

继承又分为单继承跟多继承。

顾名思义,单继承就是有一个父类多继承就是有多个父类,并且这多个父类之间不能有继承的关系,即两个类没有交集或者交集为空。

单继承:

#单继承
class Father():
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def eating(self):
        print("我吃东西了.")
    def running(self):
        print("我跑步了.")

class Son(Father):
    def __init__(self):
        pass

person = Son()
person.eating()
person.running()

效果图:

多继承:

#多继承
class Father():
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def eating(self):
        print("我吃东西了.")
    def running(self):
        print("我跑步了.")
    def speking_f(self):
        print("我是爸爸.")

class Mother():
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def eating(self):
        print("我吃东西了.")
    def running(self):
        print("我跑步了.")
    def speaking_m(self):
        print("我是妈妈.")

class Son(Father,Mother):
    def __init__(self):
        pass

person = Son()
person.speking_f()
person.speaking_m()

效果图:

4.4继承中的__init__()方法:

可能善于思考的同学会注意到,如果继承一个父类,这个父类也有一个__init__()方法,那我们子类中也有一个__init__()方法,最终执行的会是谁的呢?如果执行的是子类的,又该怎么使用父类的__init__()方法来初始化我的子类呢?

不要着急,我们慢慢来解答。

先看一段代码,相信大家就明白第一个问题的答案了:

class Father():
    def __init__(self):
        self.name = "父亲"
    def eating(self):
        print("我吃东西了.")
    def running(self):
        print("我跑步了.")
    def speking_f(self):
        print("我是爸爸.")

class Son(Father):
    def __init__(self):
        self.name = "儿子"
    def speking(self):
        print(f"我的名字是:{self.name}")

person = Son()
person.speking()

效果图:

很明显,是子类的init方法覆盖了父类的init方法,为此我们可以得出一个结论:“对于同名的属性和方法,在子类中定义的优先级大于在父类中定义的优先级。”

对于在,子类中执行父类的init方法,我们可以使用一种笨拙的方法,直接使用在类外调用类方法:

class Father():
    def __init__(self,age):
        self.name = "父亲"
        self.age = age
        
class Son(Father):
    def __init__(self,age):
        Father.__init__(self,age)
    def speking(self):
        print(f"我的名字是:{self.name},年龄是{self.age}")

person = Son("250")
person.speking()

效果图:

但是不建议使用这种方法,首先不利于阅读,其次这是非常危险的。

推荐使用super方法,讲在下文中提到。

五.super()方法

super()方法会使子类从其父类中继承所有方法和属性:

通过使用super()方法您不必使用在类外调用父类的方法,它将自动从其父类继承方法和属性。

class Father():
    def __init__(self,age):
        self.name = "父亲"
        self.age = age

class Son(Father):
    def __init__(self,age):
        super(Son, self).__init__(age)
    def speking(self):
        print(f"我的名字是:{self.name},年龄是{self.age}")

person = Son("250")
person.speking()

super()括号中,第一个参数表示子类,第二个参数表示子类的引用,而在后面init的括号中,表示需要传递的参数。

ps:“super()括号中的两个参数可以省略。

六.扩展

如果在开发中,需要对父类的方法进行修改,我们可以采用覆盖(重写)【扩展】的方式:

扩展的方式步骤

1.在子类中直接重写父类方法(麻烦)

2.在需要的位置使用super方法调用父类方法(便捷)

3.对代码特殊的位置进行特殊的编写(灵活)

其实,对于super的使用,更常见的是在子类中调用父类中封装的方法来扩展子类的方法

class Father():
    def eating(self):
        print("我在吃了.")
    def running(self):
        print("我在跑了")

class Son(Father):
    def playing(self):
        print("我在玩了")
    def eating(self):
        print("我要去吃饭啦~")
        super(Son, self).eating()
        print("我吃完啦")

person = Son()
person.eating()

效果图:

七.覆盖

7.1覆盖的含义:

在继承中,父类的有些方法在子类中不适用,子类重新定义(注意是重新定义,不是扩展!

7.2注意事项

1.若子类中“被覆盖”方法的参数类型不同,返回类型不一致,这不是覆盖,而是重载。覆盖要求参数类型必须一样,并且返回类型必须兼容。(一句话,子类对象得保证能够执行父类的一切。)

2.不能降低覆盖方法的权限,如“公共”->“私有”

3.若不希望父类中的某个方法被子类覆盖,可以使用final修饰该方法。或者在定义父类的同时,使用final来修饰类,这样表示类中所有方法均不可覆盖。

7.3重写的前提

1.参数列表必须与被重写方法一致。

2.返回类型必须与被重写方法的返回类型相同。

3.不能重写被标识为final的方法。

4.如果一个方法不能被继承,就不能重写它

例如:

class Father():
    def eating(self):
        print("我在吃了.")
    def running(self):
        print("我在跑了")

class Son(Father):
    def eating(self):
        print("我不想吃饭啦~")

person = Son()
person.eating()

这里的eating方法就被的重写了,并且保证了参数列表一致,且返回类型一致(这里没有返回值,所以返回类型肯定一致的。)

当然,如果您在Pycharm中编辑这段代码,您可以在Pycharm左边的行数处,看到如下标志:

八.多态性

8.1多态的含义

当程序不知道一个变量所引用的对象是什么类型时,仍然可以通过这个变量的调用方法,在运行过程中动态决定调用哪个对象中的方法。

例如,当子类和父类存在相同的方法的时候,子类的方法会覆盖父类的方法,这样代码在运行时总会调用子类的方法,这就是多态

判断一个实例是不是某个类的对象,可使用isinstance函数,返回True/False。

例如:

class Father():
    def eating(self):
        print("我在吃了.")
    def running(self):
        print("我在跑了")

class Son(Father):
    def eating(self):
        print("我不想吃饭啦~")

person = Son()
print(isinstance(person,Son))
print(isinstance(person,Father))

效果图:

可以看到都是True,为此我们得出结论:“当一个A类有一个父类B时,那么通过A类创建的对象,既是A类的对象又是B类的对象”。

  • 19
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Python中的继承多态是面向对象编程的重要概念。 继承是指一个可以继承另一个的属性和方法。被继承称为父或基继承称为子或派生。子可以继承的属性和方法,并且可以添加自己的属性和方法。通过继承,子可以重用父的代码,实现代码的复用和扩展。 在Python中,可以使用以下语法实现继承: ```python class ParentClass: pass class ChildClass(ParentClass): pass ``` 在上面的示例中,`ChildClass` 继承了 `ParentClass`,它可以访问和使用 `ParentClass` 中定义的属性和方法。 多态是指同一个方法名可以在不同的对象上产生不同的行为。在面向对象编程中,多态通过方法重写和方法重载来实现。 方法重写是指子定义一个与父同名的方法,从而覆盖中的方法。当调用该方法时,会执行子中的方法而不是父中的方法。 ```python class ParentClass: def greet(self): print("Hello, I am the parent.") class ChildClass(ParentClass): def greet(self): print("Hello, I am the child.") parent = ParentClass() child = ChildClass() parent.greet() # 输出:Hello, I am the parent. child.greet() # 输出:Hello, I am the child. ``` 在上面的示例中,`ChildClass` 重写了 `ParentClass` 中的 `greet` 方法,所以在子对象上调用 `greet` 方法时会执行子中的方法。 方法重载是指一个中可以定义多个同名的方法,但这些方法的参数型或个数不同。根据不同的参数型或个数,会自动选择合适的方法进行调用。 ```python class Calculator: def add(self, a, b): return a + b def add(self, a, b, c): return a + b + c calculator = Calculator() print(calculator.add(1, 2)) # 输出:3 print(calculator.add(1, 2, 3)) # 输出:6 ``` 在上面的示例中,`Calculator` 中定义了两个同名的 `add` 方法,但参数个数不同。根据传入的参数个数,会自动选择合适的方法进行调用。 这就是Python继承多态的基本概念和用法。它们可以让我们更好地组织和重用代码,提高代码的可维护性和扩展性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

是洋洋a

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

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

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

打赏作者

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

抵扣说明:

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

余额充值