python第十四课 面向对象(三)

mac2026-04-19  10

文章目录

一、继承的简介二、方法的重写三、super()四、多重继承五、多态六 类中的属性和方法类属性实例属性实例方法类方法静态方法

一、继承的简介

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

如建立如下的class:

class Person(): name = '' age = '' class Doctor(): name = '' age = '' def study(self): print('治疗病人') class Soldier(): name = '' age = '' def study(self): print('保卫国家')

在上述代码中,person、docter、soldier都具有相同的属性name、age但是在定义的时候每一个都重新定义了一次这样显得代码冗长,且复用性差,所以可以采用继承的方式来进行代码优化。 在定义类时,可以在类名后面加上括号,括号内中指定的是当前类的父类(超类、基类、super)

class Person: def __init__(self,name,age): self.name = name self.age = age class Docter(Person): def study(self): print(f'{self.name}是医生,他的职责是治疗病人') class Soldier(Person): def study(self): print(f'{self.name}是军人,他的职责是保卫国家')

调用上述代码:

p1 = Docter('张三', 23) p1.study() p2 = Soldier('李四', 22) p2.study() >>> 张三是医生,他的职责是治疗病人 >>> 李四是军人,他的职责是保卫国家

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

小练习:

# 定义一个动物类 class Animal: def run(self): print('动物跑....') def sleep(self): print('动物睡觉...') # 要定义一个狗类 # 1.直接修改动物类 - 修改起来比较麻烦,会违反ocp元组 # 2.直接创建一个新的类(狗类) - 新类比较麻烦,使用大量的复制粘贴,会出现大量的重复性代码 # 3.直接从Animal类中继承它的属性和方法 class Dog(Animal): def home(self): print('狗看家') #调用一下: dog = Dog() dog.run() dog.sleep() dog.home() # >>>动物跑.... # >>>动物睡觉... # >>>狗看家 # 如果在Dog类中重新定义了run()方法和sleep()方法,则将会覆盖掉父类中的方法,将不再继承父类中的方法如: class Dog0(Animal): def run(self): print('狗跑....') def sleep(self): print('狗睡觉...') dog1 = Dog0() dog1.run() dog1.sleep() # >>> 狗跑.... # >>> 狗睡觉...

isinstance()检查一个实例是不是属于一个类

print(isinstance(dog,Dog0)) print(isinstance(dog,Dog)) print(isinstance(dog,Animal)) # >>> False # >>> True # >>> True

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

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

二、方法的重写

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

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....

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

三、super()

定义一个动物类

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 a =Animal('猴子') a.sleep() # >>> 动物睡觉... a.run() # >>> 动物跑.... print(a.name)#因为@property 已经将name转化为了一个对象不再是一个方法了,所以直接调用,不用加括号 # >>> 猴子 a.name = '犀牛' print(a.name) # >>> 犀牛

希望可以直接调用父类的__init__来初始化父类中的属性 super()可以用来获取当前类的父类 并且通过super()返回的对象,调用父类方法时不需要传递self

class Dog(Animal): def __init__(self,name,age): # self._name = name # 希望可以直接调用父类的__init__ super().__init__(name) self._age = age def run(self): print('狗跑....') def sleep(self): print('狗睡觉...') @property def age(self): return self._age @age.setter def age(self,age): self._age = age d = Dog('二哈',10) print(d.name) # >>> 二哈 d.name = '德牧' print(d.name) # >>> 德牧 d.run() # >>> 狗跑....

四、多重继承

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

class A(object): def test(self): print('A....') # pass class B(object): def test(self): print('B中的test方法') def test2(self): print('B....') class C(B,A): pass print(C.__bases__) # >>> (<class '__main__.B'>, <class '__main__.A'>) c = C() c.test() # >>> B中的test方法 c.test2() # >>> B....

在上例中虽然class C同时继承了A、B的方法,但是在定义的过程中先继承了B类中的方法(B写在前面)此时就近在B中继承方法,如果在B中没有才会向下一个继承的类中寻找对应的方法。如:

class C(A, B): pass print(C.__bases__) c = C() c.test() c.test2()

执行结果则为

>>> (<class '__main__.A'>, <class '__main__.B'>) >>> A.... >>> 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 # 定义一个方法 def speak(obj): print('你好 %s'%obj.name) a = A('张三') b = B('李四') speak(a) speak(b) >>> 你好 张三 >>> 你好 李四

上述代码可知,定义的A、B两类都可以用speak方法调用实例a、b。同样也可以定义更多的方法来调用实例。而不同的方法调用实例呈现出来的方法也是不一样的,这个就是类的多态性。同样也可以在方法中限制多态性,代码如下:

def speak2(obj): # 类型检查 if isinstance(obj,A): print('你好 %s'%obj.name) speak2(a) # >>> 你好 张三 speak2(b) # >>> (无结果)

在该方法中,类被限制,也就是说在该方法只能调用A类的实例,不能调用B。此时就不具备多态了。

六 类中的属性和方法

类属性

class A(object): # 类属性 直接在类中定义的属性就是类属性 # 类属性可以通过类或类的实例访问到 # 类属性只能通过类对象来修改,无法通过实例对象来修改 count = 0 a = A() #创建a的实例 print(a.count) # >>> 0 a.count = 10 print(a.count) # >>> 10 print(A.count) # >>> 0 A.count = 20 print(a.count) # >>> 10 print(A.count) # >>> 20

在上述输出代码中第一个输出是实例a所继承的类属性。

实例属性

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方法........')
最新回复(0)