面向对象: ? 三大特性 : 继承 封装 多态 什么是继承: 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子
面向对象:
? 三大特性 : 继承 封装 多态
什么是继承:
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类。
python中类的继承分为:单继承和多继承。
? 在开发程序的过程中,如果我们定义了一个类A,然后又想新建立另外一个类B,但是类B的大部分内容与类A的相同时,我们不可能从头开始写一个类B,这就用到了类的继承的概念。
通过继承的方式新建类B,让B继承A,B会‘遗传’A的所有属性(数据属性和函数属性),实现代码重用。
? 用已经有的类建立一个新的类,这样就重用了已经有的软件中的一部分设置大部分,大大节省了编程工作量,这就是常说的软件重用,不仅可以重用自己的类,也可以继承别人的,比如标准库,来定制新的数据类型,这样就是大大缩短了软件开发周期,对大型软件开发来说,意义重大.
? 通过继承建立了派生类与基类之间的关系,它是一种‘是‘的关系,比如白马是马,人是动物。当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如教授是老师。
引入:继承与重用性
猫: 吃 (方法名) 喝 睡 爬树 狗: 吃 喝 睡 看家 #如果我们要分别为猫和狗创建一个类,那么就需要为 猫 和 狗 实现他们所有的功能,代码如下: class Cat: def __init__(self,name): self.name = name def eat(self): print(f'{self.name} is eating ') def drink(self): print(f'{self.name} is drinking ') def sleep(self): print(f'{self.name} is sleeping ') def climb_tree(self): print(f'{self.name} is climbing ') #类名在最后指向空间地址 class Dog: def __init__(self,name): self.name = name def eat(self): print(f'{self.name} is eating ') def drink(self): print(f'{self.name} is drinking ') def sleep(self): print(f'{self.name} is sleeping ') def house_keep(self): print(f'{self.name} is keeping the house ') 小白 = Cat('小白') 小白.eat() 小白.drink() 小白.sleep() 小白.climb_tree() # 小白 is eating # 小白 is drinking # 小白 is sleeping # 小白 is climbing 小黑 = Dog('小黑') 小黑.eat() 小黑.drink() 小黑.sleep() 小黑.house_keep() # 小黑 is eating # 小黑 is drinking # 小黑 is sleeping # 小黑 is keeping the house
继承: 解决代码的重复
1.继承语法: class A: pass class B(A): pass # B继承A,A是父类,B是子类 # A是父类 基类 超类 # B是子类 派生类 2.子类可以使用父类中的 : 方法 和 静态变量 class Animal: def __init__(self,name): self.name = name def eat(self): print(f'{self.name} is eating ') def drink(self): print(f'{self.name} is drinking ') def sleep(self): print(f'{self.name} is sleeping ') class Cat(Animal): def climb_tree(self): print(f'{self.name} is climbing ') class Dog(Animal): def house_keep(self): print(f'{self.name} is keeping the house ') 小白 = Cat('小白') # 类名 + ( ) # 先开辟空间,空间里有一个类指针-->指向Cat # 调用init方法,对象在自己的空间中找init没找到就去Cat类中找,init中也没找到,去找父类Animal中的init # class AA:pass 没有init ,并且不会报错,是因为默认继承object,object中能找到init # 所有在python3当中的类都是继承object类的,object中有init,所有的类都默认的继承object 小白.eat() 小白.drink() 小白.sleep() 小白.climb_tree() # 小白 is eating # 小白 is drinking # 小白 is sleeping # 小白 is climbing 小黑 = Dog('小黑') 小黑.eat() 小黑.drink() 小黑.sleep() 小黑.house_keep() # 小黑 is eating # 小黑 is drinking # 小黑 is sleeping # 小黑 is keeping the house 3.当子类和父类的方法重名的时候,我们只使用子类的方法,而不会去调用父类的方法。 子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。 class Animal: def __init__(self,name): self.name = name def eat(self): print(f'{self.name} is eating ') def drink(self): print(f'{self.name} is drinking ') def sleep(self): print(f'{self.name} is sleeping ') class Cat(Animal): def eat(self): print(f'{self.name} is eating ') def climb_tree(self): print(f'{self.name} is climbing ') 小白 = Cat('小白') 小白.eat() # 小白 is eating 4.子类想要调用父类的方法的同时还想执行自己的同名方法,在子类的方法中调用父类的方法 :父类名.方法名(self) # 比如:猫和狗在调用eat的时候既调用自己的也调用父类的 class Animal: def __init__(self,name,food): self.name = name self.food = food self.blood = 100 #血条 self.wisdom = 100 #智慧 def eat(self): print(f'{self.name} is eating {self.food}') def drink(self): print(f'{self.name} is drinking ') def sleep(self): print(f'{self.name} is sleeping ') class Cat(Animal): def eat(self): self.blood += 100 #吃了东西后血条+100 Animal.eat(self) #在子类的方法中调用父类的方法 :父类名.方法名(self) 手动添加self,把self传进去。类名调用方法名时不会自动传对象 def climb_tree(self): print(f'{self.name} is climbing ') self.drink() #爬树的过程中喝水 当自己没有喝水的方法时,直接调用父类的方法 class Dog(Animal): def eat(self): self.wisdom += 100 #吃了东西后智慧+100 Animal.eat(self) def house_keep(self): print(f'{self.name} is keeping the house ') 小白 = Cat('小白','猫粮') 小黑 = Dog('小黑','狗粮') 小白.eat() 小黑.eat() print(小白.__dict__) print(小黑.__dict__) # 小白 is eating 猫粮 # 小黑 is eating 狗粮 # {'name': '小白', 'food': '猫粮', 'blood': 200, 'wisdom': 100} #吃了东西后血条+100 # {'name': '小黑', 'food': '狗粮', 'blood': 100, 'wisdom': 200} #吃了东西后智慧+100 小结: 继承语法 class 子类名(父类名):pass 父类和子类方法的选择: 1.子类的对象,如果去调用方法,永远优先调用自己的 2.如果自己有 ,用自己的 3.自己没有 ,用父类的 4.如果自己有 还想用父类的 : 直接在子类方法中调父类的方法 父类名.方法名(self) # 思考一:下面代码的输出? class Foo: def __init__(self): self.func() # 在每一个self调用func的时候,我们不看这句话是在哪里执行,只看self是谁 def func(self): print('in foo') class Son(Foo): def func(self): print('in son') Son()#in son # 思考二: 如果想给狗和猫定制个性的属性 # 猫 : eye_color眼睛的颜色 # 狗 : size型号 class Animal: def __init__(self, name,food): self.name = name self.food = food self.blood = 100 self.wisdom = 100 def eat(self): print('%s is eating %s'%(self.name,self.food)) def drink(self): print('%s is drinkig'% self.name) def sleep(self): print('%s is sleeping'% self.name) class Cat(Animal): def __init__(self,name,food,eye_color): Animal.__init__(self,name,food) # 调用了父类的初始化,去完成一些通用属性的初始化 self.eye_color = eye_color # 派生属性 class Dog(Animal): def __init__(self, name, food, size): Animal.__init__(self, name, food) self.size = size 小白 = Cat('小白','猫粮','蓝色') print(小白.__dict__)#{'name': '小白', 'food': '猫粮', 'blood': 100, 'waise': 100, 'eye_color': '蓝色'} 小黑 = Dog('小黑','狗粮','big') print(小黑.__dict__)#{'name': '小黑', 'food': '狗粮', 'blood': 100, 'waise': 100, 'size': 'big'}
单继承:
# 调子类的 : 子类自己有的时候,调子类的 # 调父类的 : 子类自己没有的时候,就调父类的 # 调子类和父类的 :子类父类都有,在子类中调用父类的 #单继承: class D: def func(self): print('in D') class C(D): def func(self): print('in C') class B(C): def func(self): print('in B') class A(B): def func(self): print('in A') A().func() # a = A() ---> a.func() # in A
多继承:
# 多继承 有好几个爹 有一些语言不支持多继承 java python语言的特点 : 可以在面向对象中支持多继承 一个类有多个父类,在调用父类方法的时候,按照继承顺序,先继承的哪个,就先去哪个寻找 class A: def func(self):print('in A') class B: def func(self):print('in B') class C(A,B):pass C().func()#in A class C(B,A):pass C().func()# in B
知识点补充:
1.object 类: object类 是 类祖宗, 所有在python3当中的类都是继承object类的, object中有init,所有的类都默认的继承object。 class A: pass a = A() 写成: class A(object): pass a = A() 2.__bases__ 如果没有指定基类,python的类会默认继承object类,object是所有python类的基类。 class A:pass print(A.__bases__)#(<class 'object'>,) class C:pass print(C.__bases__)#(<class 'object'>,) class B(A,C):pass print(B.__bases__)#(<class '__main__.A'>, <class '__main__.C'>) #只显示所有父类,不显示爷爷类 3.isinstance 和 type ## isinstance isinstance(obj,cls)检查是否obj是否是类 cls 的对象 a = 1 b = 'abc' print(isinstance(a,int))#True print(isinstance(a,float))#False print(isinstance(b,str))#True ## type a = 1 b = 'abc' print(type(a) is int)#True print(type(b) is str)#True # class Cat: pass 小白 = Cat() print(type(小白) is Cat)#True print(isinstance(小白,Cat))#True # class Animal:pass class Cat(Animal):pass 小白 = Cat() print(type(小白) is Cat)#True print(type(小白) is Animal)#False print(isinstance(小白,Cat))#True 判断对象是不是类的对象 print(isinstance(小白,Animal))#True 判断对象是不是子类的对象 4.绑定方法和普通的函数: from types import FunctionType,MethodType # FunctionType : 函数 # MethodType : 方法 #【面试】 方法和函数的区别不在于是否写在类里边,而在于谁调用它,和函数写在哪里无关: 用类名调用类的函数就是函数 用对象调用类的函数就是方法 class A: def func(self): print('in func') print(A.func)#函数 <function A.func at 0x000002610CE79400> print(isinstance(A.func,FunctionType))#True print(isinstance(A.func,MethodType))#False a = A() print(a.func)#方法 <bound method A.func of <__main__.A object at 0x000002610CD07DD8>> print(isinstance(a.func,MethodType))#True print(isinstance(a.func,FunctionType))#False 5.其他: class A: role = '法师' def func1(self):pass def func2(self):pass class B:pass class C(B,A):pass 【1】 类名.__base__# 类的第一个父类 print(A.__base__)#<class 'object'> print(C.__base__)#<class '__main__.B'> 【2】 类名.__bases__# 类所有父类构成的元组 print(C.__bases__)#(<class '__main__.B'>, <class '__main__.A'>) 【3】我们定义的类的属性有两种方式查看: dir(类名):查出的是一个名字列表 #类的字典属性 类名.__dict__:查出的是一个字典,key为属性名,value为属性值 print(A.__dict__)#{'__module__': '__main__', 'role': '法师', 'func1': <function A.func1 at 0x0000026EA0B68AE8>, 'func2': <function A.func2 at 0x0000026EA0B68B70>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None} 【4】 类名.__name__# 类的名字(字符串) 函数名也可通过此方式查看 print(A.__name__)#A 【5】 类名.__class__ 实例对应的类(仅新式类中) 自定义类默认为type类型 print(A.__class__)#<class 'type'> print(B.__class__)#<class 'type'> print(C.__class__)#<class 'type'> 【6】 类名.__module__# 类定义所在的模块 print(C.__module__)# __main__ #如果下面这句话在 module.py模块中 print(C.__module__)#__main__ # 导入module模块 import module # 结果: module 【7】 __doc__ 查看函数或类的注释 #项目中要给类和函数添加注释 def func(): ''' 这个函数主要是用来卖萌 ''' pass print(func.__doc__)# 这个函数主要是用来卖萌 class Cat: ''' 这个类是用来描述游戏中的猫咪角色 ''' pass print(Cat.__doc__)# 这个类是用来描述游戏中的猫咪角色 6.使用pickle存取自定义类的对象的方式 #前提:必须有类 #通过pickle 存储和读取对象 class Course: def __init__(self,name,period,price): self.name = name self.period = period self.price = price python = Course('python','6 moneth',21800) linux = Course('linux','5 moneth',19800) go = Course('go','4 moneth',12800) import pickle with open('pickle_file','ab') as f: pickle.dump(python,f) pickle.dump(linux,f) pickle.dump(go,f) with open('pickle_file','rb') as f: while True: try: obj = pickle.load(f) print(obj.name,obj.period,obj.price) except EOFError: break # python 6 moneth 21800 # linux 5 moneth 19800 # go 4 moneth 12800