- 封装
- 继承
- 多态
- 封装就是对对象的成员进行访问限制。
- 封装的三个级别:
- 公开的:public
- 受保护的: protected
- 私有的:private
- 注意:public,protected,private不是关键字
- 判断对象的位置:对象内部、对象外部、子类中和跨模块访问
- 公共的封装实际对成员没有任何操作,没有限制,任何地方都可以使用
- 受保护的封装是将对象成员进行一定级别的封装,
- 在类中或者子类中都可以访问,
- 在外部不可以访问:此变量不能通过from XXX import xxx 导入
- 封装方法:在成员名称前添加一个下划线就可以
- 私有成员时最高级别的封装,只能在当前类或对象中访问
- 在成员面前添加两个下划线__.
- 私有化方法(私有化函数)和私有化成员一样
- 私有成员只是一种改名策略,可以使用.__dict__查看改名后的内容
# 封装到对象中的属性是一种封装。 类本身就算是一种封装 class Person: country = ‘China‘ # 公开的 _addr = 555 # 被保护的 __sch = "zhkai" # 私有的 def __init__(self, sex, name, age): self.name = name # 公开的 self._sex = sex # 被保护的 self.__age = age # 私有的 def func(self): # 公开的 print(self.name) def _func1(self): # 被保护的 print(self._sex) def __func2(self): # 私有的 print(self.name) def func3(self): # 私有的可以在类内部进行访问 print("__sch:", self.__sch, " ","__age:", self.__age) # 实例化对象 p1 = Person("man", ‘xiaming‘, 39) p2 = Person("girl",‘lisi‘, 18) """-------------------------------------------------------""" # 1.公开的没有限制 p1.func() # xiaming print(p1.country, p2.country, Person.country) # China China China """-------------------------------------------------------""" # 2.被保护的能在类中调用 # 2.1在类中或者子类中都可以访问 # 2.2在外部不可以访问:此变量不能通过from XXX import xxx 导入 p2._func1() # girl print(p1._addr, p2._addr, Person._addr) # 555 555 555 """-------------------------------------------------------""" # 3.私有的 # 3.1父类以及类的外部不能访问 # print(Person.__name) # p1 = Person() # print(p1.__name) # 3.2 在类的内部可以调用 p1.func3() # __sch: zhkai __age: 39 p2.func3() # __sch: zhkai __age: 18 # 3.3通过改名访问 # 执行类的内容时,发现”__“的变量名时,系统会自动将其改名 # 可以使用.__dict__查看,发现改名为 classname._classname__attributename # 例如:__age 改为 _Person__age p2._Person__func2() # lisi print(p2._Person__age, p2.__dict__[‘_Person__age‘], Person.__dict__[‘_Person__sch‘]) # 18 18 zhkai
- property(fget=None, fset=None, fdel=None, doc=None)
- 第一个参数时获得属性的方法名。
- 第二个参数是设计属性的方法名。
- 第三个参数是删除属性的方法名。
- 返回一个设置属性的属性。
class Person: def __init__(self,name): self.name = name def getName(self): return self.name def setName(self, value): self.name = value def delName(self): del self.name x = property(getName,setName,delName) p = Person("dd") print(p.x) # dd # 如果p 是 Person的实例化, p.x 将触发 getter,p.x = value 将触发 setter , del p.x 触发 deleter。 p.name = 55 print(p.x) # 55
- 在继承关系中,原来设计好的称作父类,新设计的类称作子类。
- 继承是为了代码复用和设计复用而设计的
- 继承就是一个类可以获得另外一个类中的成员属性和成员方法。
- 继承与被继承:
- 被继承的类叫父类,也叫基类,也叫超类
- 用于继承的类,叫做子类,也叫派生类
- 继承与被继承一定存在一个is-a的关
class 类名(被继承的类):
- 概念:
- 单继承:每个类只能继承一个类,仅仅继承一个父类
- 多继承:每个类允许继承多个类,继承了多个父类
- 无重叠的多继承
- 有重叠的多继承
- 优缺点
- 单继承:
- 传承有序逻辑清晰语法简单隐患少
- 功能不能无限扩展,只能在当前唯一的继承链中扩展
- 多继承:
- 优点:类的扩展功能方便
- 缺点:继承关系混乱
# 1.简单的继承 class A(): pass class C(): pass # 1.1单继承 class B(A): pass # 1.2多继承 class Person(A, C): pass # 注意:创建了类就会继承object # 1.3查看对象 print(B.__class__) print(type.__class__) # 1.4查看父类:使用__bases__ print(B.__bases__) # 单继承,只有一个父类 print(Person.__bases__) # 多继承,包含了两个父类 print(int.__bases__, bool.__bases__) """ # 结果 <class ‘type‘> <class ‘type‘> (<class ‘__main__.A‘>,) (<class ‘__main__.A‘>, <class ‘__main__.C‘>) (<class ‘object‘>,) (<class ‘int‘>,) """
- 所有的类都继承object类,即所有的类都是object类的子类。
- 子类可以继承它的父类的任何属性和方法,可以使用父类里除了私有成员外所有内容。
- 子类只是通过引用关系访问父类的资源,只能读取,而不是修改。
# 2.1资源的使用 # 定义父类(超类) class Person(): name = "China" # 公有的 __age = 18 # 私有的 _addr = 56 # 被保护的 def sleep(self): print("Sleeping....") # 定义子类 class Teacher(Person): teacher_id = "9527" def make_test(self): print("attention") t = Teacher() # 1.子类可以继承它的父类的任何属性和方法,可以使用父类里除了私有成员外所有内容 # 1.1访问公有的、被保护的属性和方法 print(t.name, t._addr) # China 56 t.sleep() # Sleeping.... # 1.2无法访问私有属性和方法 # print(t.__age) # 会报错 但是还是可以通过改名访问print(t._Person__age) # 1.3 子类实例化对象访问自己的属性和方法 print(t.teacher_id) # 9527 t.make_test() # attention # 1.4用父类的资源,只能读取,而不是修改 # Teacher中没有name的属性,利用Teacher.__dict__查看 # 给Teacher增加了name属性,没有修改Person的name Teacher.name = "201888" # 修改后 print(Teacher.__dict__) # ‘name‘: ‘201888‘ print(Person.__dict__) # ‘name‘: ‘China‘,
- 子类中定义与父类同名的方法或属性
- 则优先使用子类,会自动覆盖父类对应的方法或属性。
class B(): age = 18 class A(B): age = 28 t = A() print(A.__dict__) print(A.__dict__) # 子类和父类定义同一个名称变量,则优先使用子类 print(t.age) """ # 结果 {‘__module__‘: ‘__main__‘, ‘age‘: 28, ‘__doc__‘: None} {‘__module__‘: ‘__main__‘, ‘age‘: 28, ‘__doc__‘: None} 28 """
- 在一个类的基础上增加一些额外的资源。
- 子类相比父类多一些自特有的资源,子类中可以定义独有的成员属性和方法
- 被覆盖的额基础上,新增内容
- 子类如果扩充父类方法
- 可以在定义新方法的同时访问父类成员来进行代码重用,
- 可以使用 [父类名.父类成员]的格式来调用父类成员,
- 也可以使用super(),父类成员的格式调用
# 1.通过实例化对象增加 class Hum(): a = 1 def __init__(self): self.b = 2 class Person(Hum): c= 3 p = Person() p.a = 77 print(p.__dict__) """--------------------------------------------------------------------------""" # 2.通过父类,在父类内增加 # 注意;这种情况是子类没有构造函数,不能覆盖父类的构造函数 class Hum(): a = 1 def __init__(self): self.b = 2 self.a = 77 # 增加的属性 class Person(Hum): c= 3 p = Person() print(p.__dict__) """--------------------------------------------------------------------------""" # 3.通过子类,在子类内增加 # 注意:如果子类有构造函数,会覆盖父类的构造函数的。 class Hum(): a = 1 def __init__(self): self.b = 2 class Person(Hum): c= 3 def __init__(self): Hum.__init__(self) # 引用B中的实例化属性,解决被覆盖的问题 self.a = 77 # 增加的属性 p = Person() print(p.__dict__) """--------------------------------------------------------------------------""" # 4.通过super class Hum(): a = 1 def __init__(self): self.b = 2 class Person(Hum): c= 3 def __init__(self): super(Person, self).__init__() # 实现父类功能 # super().__init__() # 这种写法也可以 self.a = 77 p = Person() print(p.__dict__) """--------------------------------------------------------------------------""" # 5子类扩充夫类功能 # 直接调用父类相应的功能,或者通过super class Person(): def sleep(self): print("Sleeping....") def work(self): print("make some money") class Teacher(Person): def make_test(self): print("attention") def work(self): # 扩充父类功能只需调用父类相应的函数 # Person.work(self) super().work() self.make_test()# 此处是扩充 # 扩充父类的另一种方法,super 代表得到父类 t = Teacher() # make some money
t.work() # attention
- 是一类特殊的函数,在进行实例化之前进行调用
- 如果定义了构造函数,则实例化时使用构造函数,不查找父类构造函数
- 如果没有定义,则自动查找父类构造函数
- 如果子类没定义,父类构造函数带参数,则构造对象时的参数应该按父类参数构造
- 任何情况优先查找自己的变量
- 自己没有就查找父类
- 构造函数如果本类中没有定义,则自动查找调用父类构造函数
- 如果本类有定义,则不继续往上查找
# 继承里面的构造函数 class A(): def __init__(self): print("A__init__") class B(): def __init__(self): print("B__init__") class C(B): def __init__(self): print("C__init__") class D(A): pass class E(): pass p1 = A() # 自动调用A的构造函数 p2 = D() # 自动调用A的构造函数, # 因为D中没有构造函数,只能调用父类的构造函数 p3 = C() # 自动调用C的构造函数 # 父类B的构造函数被覆盖了,C中已经存在各种函数 # p3 = E() # 会报错,E()没构造函数
- super()的作用是:
- 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,
- 但有时,我们希望能同时实现父类的功能,
- 这时,我们就需要调用父类的方法了,可通过使用 super 来实现。
- super(参数1,[参数2])
- 沿着参数2的MRO链条,找参数1 的节点
- 切记不要使用动态参数,self.__class__,容易出错
- super不是关键字,而是一个类
- super的作用时获取MRO(MethodResolustionOrder)列表中的第一个类
- 与父类没有实质关系,可以通过super 调用父类
- super 的两个使用方法:参见构造函数中调用父类的构造函数
- 沿着MRO链条,找到下一级节点,去调用对应的方法
- 多态就是同一个对象在不同情况下由不同的状态出现
- 一个类所延伸的多种形态
- 调用时的多种形态
- 多态不是语法,是一种设计思想
- 多态性:一种调用方式,不同执行效果
- 多态:同一种事物的多种形态,
- [多态和多态性](http://www.cnblogs.com/luchuangao/p/6739557.html)
- Mixin设计模式
- 主要采用多继承方式对类的功能进行扩展
- 网上阅览资料
- 我们使用多继承语法来实现Mixin
- 使用时
- 首先必须表示某一单一功能
- 职能必须单一,如果有多个,则写多个Mixin
- Mixin不能依赖子类的实现
- 子类即使没有继承这个Mixin类,照样能工作,只是缺少了某个功能
- 优点
- 可以在不对类进行修改的情况下,扩充功能
- 可以方便的组织和维护不同功能组建的划分
- 可以根据需要任意调整功能类的组合
- 可以避免创建很多新的类,导致类的继承混乱
原文:https://www.cnblogs.com/cmn-note/p/11247619.html