基础十四:面向对象三

mac2024-10-26  51

一、继承的简介

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

class Person(): name = '' age = '' class Doctor(): name = '' age = '' def study(self): print('治病救人') class Sldie(): 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('狗看家.。。') pass d = Dog() # print(d) #<__main__.Dog object at 0x000001A6BE4F4148> # d.run() #狗跑..。。 # d.sleep() #动物睡觉.。。 r = isinstance(d,Dog) print(r) #True s = isinstance(d,Animal) print(s) #True 若創建类的时候省略了父类,则默认父类是object object是所有类的父类,所有类都继承了object class Person(): pass # issubclass()--检查一个类是不是另一个类的子类 print(issubclass(Dog,Animal)) #True print(issubclass(Dog,object)) #True print(issubclass(Animal,object)) #True print(issubclass(Person,object)) #True

二、方法的重写

若在子类中有和父类同名的方法,通过子类的实例去调用方法时,会调用子类的方法,而非父类的方法 这就是方法的重写(覆盖)

当我们去调用一个对象的时候 会优先调用当前对象的方法,若当前对象中没有这个方法,则会去父类中寻找,若其父类中 也没有,则会去父类的父类寻找,若无,则会逐级向上,直到object中去,若object也没有,会报错

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.sty() #AttributeError: 'C' object has no attribute 'sty'

三、super()

父类中所有的方法都会被子类继承,包括特殊方法

#定义一个动物类 class Animal: def __init__(self,name): self._name = name def run(self): print('动物跑..。。') def sleep(self): print('动物睡觉.。。') @property def name(self): # print('property执行') 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 # Animal.__init__(self,name) super().__init__(name) self._age = age def run(self): print('狗跑..。。') # # def sleep(self): # print('狗睡觉.。。') # def home(self): print('狗看家.。。') @property def age(self): # print('property执行') return self._age @age.setter def age(self, age): self._age = age # e = Dog() #TypeError: __init__() missing 1 required positional argument: 'name' #子类未重写init方法之前,即注释方法def __init__(self,name,age): # e = Dog('蛇精病') # print(e.name) #蛇精病 # e.name = '二哈' # print(e.name) #二哈 #子类未重写init方法之后 e = Dog('long',3) print(e.name,e.age) #long 3

四、多重继承

语法:类名.__bases__可以用了获取当前类的所有父类 在Python中是支持多重继承的,也就是我们可以为一个类同时指定多个父类 在开发中没有特殊情况,尽量避免使用多重继承,因为多重继承会让我们代码过于复杂 如果多个父类中有同名的方法,则会在第一个父类中寻找,然后找第二个…(父类顺序以写入的顺序为准) 前边会覆盖后面的

class A(object): def test(self): print('A....') class B(object): def test2(self): print('B....') class C(A,B): pass print(C.__bases__) #(<class '__main__.A'>, <class '__main__.B'>)-元组 print(A.__bases__) #(<class 'object'>,)-元组 print(B.__base__) #<class 'object'> c = C() c.test() #A.... 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 # def __len__(self): # # return 5 @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('钢铁侠') # print(len(b)) #TypeError: object of type 'B' has no len() c = C() speak(b) #你好 钢铁侠 speak2(a) ##你好 葫芦娃 speak2(b) #因为speak2中设置了对象的检查,只有A类型的可以输出,所以此时没有输出 # len() lst = [1,2,3] s = 'python' print(len(lst)) #3 print(len(s)) #6 # 刚才用len()函数来检查不同对象类型的长度其实就是面向对象的特征之一 # 之所有len()这个函数能获取长度,是因为这些对象中具有一个特殊方法__len__ # 换句话说只要对象中有__len__特殊方法,就可以通过len()方法来获取它的长度 # 面向对象的三大特征 # 封装 确保对象中的数据更安全 # 继承 保证了对象的可扩展性 # 多态 保证了程序的灵活性 # len() lst = [1,2,3] s = 'python' print(len(lst)) #3 print(len(s)) #6 刚才用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 print('A ',A.count) # A 0 print('a ',a.count) # a 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) # AttributeError: type object 'A' has no attribute 'name' a.test() # 实例对象在调用--我是test方法 # A.test() # TypeError: test() missing 1 required positional argument: 'self' A.test(2) #类对象在调用-我是test方法 # a.test() 等价于 A.test(a) A.test2() #我是test2方法......... <class '__main__.A'> 8 a.test2() #我是test2方法......... <class '__main__.A'> 8 # A.test2() 等价于 a.test2() A.test3() #我是test3方法........ a.test3() #我是test3方法........ # 类属性 # 实例属性 # 类方法 # 实例方法 # 静态方法
最新回复(0)