一、组合
1. 什么是组合
一个对象的属性是来自于另外一个类的对象,称之为组合
2. 为何用组合
(1)组合也是用来解决类与类代码冗余的问题
(2)数据不重复 (继承可能无法解决)
(3)不需要父类的所有的属性,要什么拿什么 (继承无法解决)
3、怎么用组合
# class Foo: # aaa=1111 # def __init__(self,x,y): # self.x=x # self.y=y # # def func1(self): # print('Foo内的功能') # # # class Bar: # bbb=2222 # def __init__(self, m, n): # self.m = m # self.n = n # # def func2(self): # print('Bar内的功能') # # obj1=Foo(10,20) # obj2=Bar(30,40) # # obj1.xxx=obj2 # # # print(obj1.x,obj1.y,obj1.aaa,obj1.func1) # print(obj1.xxx.m,ob
foo的对象obj1通过某个属性xxx指向另一个类bar的对象obj2,可以用obj1.xxx来调用obj2的属性,包括了bar的属性
充分利用组合这一特点,在某些情况,比继承更精简,没有数据重复,没有多余属性的必要(为什么要用组合)
二、封装
1、什么是封装
装指的是把属性装进一个容器
封指的是隐藏的意思,但是这种隐藏式对外不对内的
2. 为何要封装
封装不是单纯意义的隐藏
封装数据属性的目的:将数据属性封装起来,类外部的使用就无法直接操作该数据属性了
需要类内部开一个接口给使用者,类的设计者可以在接口之上附加任意逻辑,从而严格
控制使用者对属性的操作
封装函数属性的目的:隔离复杂度
3. 如何封装
只需要在属性前加上__开头,该属性就会被隐藏起来,该隐藏具备的特点:
1. 只是一种语法意义上的变形,即__开头的属性会在检测语法时发生变形_类名__属性名
2. 这种隐藏式对外不对内的,因为在类内部检测语法时所有的代码统一都发生的变形
3. 这种变形只在检测语法时发生一次,在类定义之后新增的__开头的属性并不会发生变形
4. 如果父类不想让子类覆盖自己的属性
# class fool: # def f1(self): # print('fool.f1') # def f2(self): # print('fool.f2') # self.f1() # class bar(fool): # def f1(self): # print('bar.f1') # # obj=bar() # obj.f2()
让外部访问到内部,需要开一个接口访问
class People: def __init__(self,name,age): self.__name=name #_People__name self.__age=age #_People__age def tell_info(self): print(self.__name,self.__age) def new_info(self,name,age): self.__name=name self.__age=age obj=People('egon',18) obj.new_info('huihui',18) obj.tell_info()
三。多态
1. 什么是多态
同一种事物的多种形态
2. 为何要用多态
多态性:指的是可以在不用考虑对象具体类型的前提下而直接使用对象下的方法
3. 如何用多态
# import abc # # class Animal(metaclass=abc.ABCMeta): (强制让子类拥有某个属性) # @abc.abstractmethod # def speak(self): # pass # # # Animal() # 父类不能实例化,因为父类本身就是用来制定标准的 # class People(Animal): # def speak(self): # print('say hello') # # def jiao(self): # # print('say hello') # # class Dog(Animal): # def speak(self): # print('汪汪汪') # # class Pig(Animal): # def speak(self): # print('哼哼哼') # # # peo=People() # dog1=Dog() # pig1=Pig() # # # # # peo.speak() # dog1.speak() # pig1.speak() def speak(animal): animal.speak() speak(peo) speak(dog1) speak(pig1)
四、装饰器property
在封装的情况下,在接口上通过装饰器property把技能(函数)伪装成属性,让使用者认为是直接访问的是类
class People: def __init__(self,name): self.__name=name @property 伪装成属性 def look(self): return '<名字:%s>' %self.__name @look.setter 修改功能的伪装 def look(self,new_name): self.__name=new_name @look.deleter 删除功能的伪装 def look(self): del self.__name obj=People('huihui') print(obj.look) obj.look='egon' print(obj.look)