面向对象的三大特性:

  1. 封装:
    1. 在类的内部(class内部)可以由属性和方法,外部代码可以通过直接调用实例变量的方法来操作数据,这样就隐藏了内部的逻辑,但是外部还是可以直接修改实例的属性,因此当需求中存在需要内部属性不被外部访问,就可以把属性的名称前加__。
    2. 在Python中,实例的变量如果是以__开头的,就变成一个私有化属性,只有内部可以访问,外部不能访问。
"""
什么是封装:
装;网容器即名称空间里面存入名字
封; 代表将存放与名称空间中的名字给藏起来,这种隐藏对外不对内 为什么要封装:
封数据属性:将数据属性隐藏起来,类外部无法直接操作属性,需要类内开辟一个接口来外部使用可以间接的操作属性,可以在接口内定义任意的控制逻辑,从而严格控制使用者对属性的操作
封函数属性:隔离复杂度(开机只有一个按键实际上却又很多操作) 如何封装:
在类定义的属性前加__开头,(没有__结尾) 底层原理:
# __开头的属性实现隐藏,只是语法层面上的变形,并不会真的限制类外部的访问
# 该变形操作只在类定义阶段检测语法时发生一次,类定义阶段之后新增的__开头的属性并不会变形
# 如果父类不想让子类覆盖自己的属性,可以在属性前加__开头
"""
class Student:

    def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender def study(self):
print('学生%s,正在学习' % self.name) st1 = Student('qzk', 18, 'male')
print(st1.__dict__) # {'name': 'qzk', 'age': 18, 'gender': 'male'} class Student: def __init__(self, name, age, gender):
self.name = name # 姓名未隐藏封装
self.__age = age # 年龄设置为私有化属性
self.__gender = gender # 性别设置为私有化属性 def __study(self): # 类的函数属性也可以私有化
print('学生%s,正在学习' % self.name) @property # property 语法糖是将函数属性伪装成数据属性
def age(self): # 以函数伪装成数据的形式,通过 obj.age方式,去查看对象的私有化属性obj.__age
return self.__age @age.setter # 在property 装饰的函数下,内置了一个函数名.setter装饰器,用来修改私有化属性,作为修改私有化属性的接口
def age(self, age):
if not isinstance(age, int):
raise TypeError('请输入正确的数据类型:int')
else:
self.__age = age st2 = Student('qzk', 18, 'male')
print(st2.__dict__) # {'name': 'qzk', '_Student__age': 18, '_Student__gender': 'male'}
# 我们发现,被封装的属性,在名称空间的字典中存储的形式是'_类名__属性名',这在底层就是一种封装,属性私有化一种实现
# 我们发现如果真的想访问该属性,可以使用如下方式:
print(st2._Student__age) # 18 该方式是直接访问底层的字典里面信息,一般不建议这样操作
# print(st2.__age) # AttributeError: 'Student' object has no attribute '__age',这样访问会报错,无法访问 # 如果我们真的想访问该信息,一般我们会开一个借口并对其加以控制
print(st2.age) #
st2.age = 19
print(st2.age) #
st2.age = '十八' # raise TypeError('请输入正确的数据类型:int')
# TypeError: 请输入正确的数据类型:int # property 装饰器,是用来将类的函数属性伪装成数据属性,被装饰过后的函数属性,是不可以进行增删改查操作的,
# 但是如果实际真的需要增删改查,则需要在所开接口上方进行装饰器(函数名.setter)操作

二、继承:

  1. 分类: 继承分为单继承和多继承
  2. 定义: 在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。
"""
继承的特点:
  1.在python中,一个子类可以同时继承多个父类
  2.在继承背景下去说,python中的类分为两种:新式类 和 经典类
    1.新式类: 但凡继承object的类,以及该类的子类,都称为新式类(python3中,所有继承关系,父类都默认继承object,因此都是新式类)
    2.经典类:经典类的概念只有在python2中存在,python2中类的继承,父类不默认继承object,如果是新式类,需要手动继承object。
    3.在新式类中属性的查找顺序(按照广度优先原则,最后查找object),在经典类中按照深度优先的原则。
    4.新式类与经典类的区别:继承中属性查找的实现原理不同
  3.继承: 利用继承来解决类与类之间的方法冗余问题
  4.派生:在子类派生的新方法中重用父类的功能和方法
"""
# 抽离:先有多个有共同点的类,抽离出共性形成的类 => 父类
# 派生:通过已有的父类,再去定义该类的子类,这种方式就叫做派生 # 继承:继承是一种关系,子类可以通过父类获取属性和方法,能获取的根据就是继承 # 继承的语法:
# class 父类名:pass
# class 子类名(父类名): pass
class Sup:
pass
class Sub(Sup):
pass # 继承的规则
# 1.父类的所有未封装的属性和方法,子类都能访问
# 2.父类的所有封装的属性和方法,子类都不能访问
# -- 在外界通过子类或子类对象,不能访问
# -- 在子类内部通过子类或子类对象也不能访问 class Sup:
__num = 10 # 封装被更名为_Sup__num
class Sub(Sup):
def test(self):
print(self.__num) # 本质去访问_Sub__num,所以不能访问 # 继承父类的方法:子类没有明文书写父类的方法,通过继承关系拿到
class Sup:
def test(self):
print(self) # 父类对象调用就是父类对象,子类对象调用就是当前调用的子类对象 class Sub(Sup):
pass
Sub().test() # 重写父类的方法:子类明文书写父类同名的方法,并且实现体自定义
class Sup:
def test(self):
print(self) # 父类对象调用就是父类对象,子类对象调用就是当前调用的子类对象 class Sub(Sup):
def test(self):
print('自己的方法', self)
Sub().test() # 重用父类的方法:子类明文书写父类同名的方法,有自己的实现体,但也用父类原有的功能
class Sup:
def test(self):
print(self) # 父类对象调用就是父类对象,子类对象调用就是当前调用的子类对象 class Sub(Sup):
def test(self):
super().test() # 本质 super(Sub, self).test() py2必须这么写
print('自己的方法', self)
Sub().test()

  super()方法

class Sup:
def __init__(self, name):
self.name = name def test(self):
print(self) class Sub(Sup):
# 默认父级的__init__可以被继承过来,
# 但是会出现子类对象的属性比父类多
def __init__(self, name, salary):
super().__init__(name) # 父级有的共性功能通过super()交给父级做
self.salary = salary # 子类特有的自己来完成 # 有继承关系下,只要名字相同,即使参数不同,还是属于同一个方法
def test(self, num):
super().test() # 使用父级的方法
print(num) # 外界通过Sub对象来调用test方法,一定找自己的test方法(属性的查找顺序) # 重点:super() 可以得到调用父级功能的对象,调用者还是子类对象
# -- super()只能在子类的方法中使用
# -- super()本质 super(子类类名, 当前对象)
# -- super().父类普通方法 | super().__init__() | super()能调用父类所有可继承方法
'''
继承 1.父类:在类后()中写父类们
class A:pass
class B:pass
class C(A, B):pass 2.属性查找顺序:自己 -> ()左侧的父类 -> 依次往右类推 3.抽离:先定义子类,由子类的共性抽离出父类 - 派生:父类已经创建,通过父类再去派生子类 4.继承关系
-- 1)父类的所有非封装的属性和方法均能被继承
-- 2)父类的所有封装的属性和方法均能被继承
-- 3)在子类中要去使用父类的方法
-- 子类继承父类方法:子类不需要去实现父类的方法,子类对象可以直接调用父类方法
-- 重写父类的方法:方法名与父类相同,实现体与父类不同,子类对象调用的是自身方法
-- 重用父类的方法:方法名与父类相同,实现体中有自己的逻辑也调用了父类的方法(super())
-- super():在子类中获取可以调用父类方法的对象,且在父类中体现的调用者子类或子类对象 5.复杂继承:一个类可以继承多个类,查找顺序是根据继承父类从左往右的顺序,并且在查找第一个父类时,将父类的父类也进行查找(一个父类分支全部查找完毕才去查找下一个父类分支) 6.棱形继承
-- 经典类:py2中类不默认继承object,所以没有明确继承的类就没有继承任何类,这样的类称之为经典类
-- 新式类:所有直接或间接继承object的类,py2中主动继承object的类及py3中所有的类 -- 前提:父类中有共有属性或方法,子类没有自己去定义这些属性和方法,必须从父类中获取,到底从哪个父类中获取
-- 经典类:深度查找 a -> b -> d -> c
-- 新式类:广度优先 a -> b -> c -> d
d
b c
a
'''

super().属性    方法与    类名.属性    方法    调用父类属性在继承上的区别

"""
在子类派生出啦的新方法中重用父类功能2:super()必须在类中用
super(自己的类名,自己的对象) 必须在类中用
在python3中,
super()
调用该函数会得到一个返回值,是一个特殊的对象,该对象专门用来访问父类的属性!!!完全按照mro列表 总结:严格依赖继承的mro表
访问是绑定方式,有自动传值的效果 """
  1. 多态:

    # 多态:对象的多种状态 - 父类对象的多种(子类对象)状态
    
    import abc
    class People(metaclass=abc.ABCMeta):
    def __init__(self, name):
    self.name = name
    @abc.abstractmethod
    def speak(self): pass class Chinese(People):
    def speak(self):
    print('说中国话')
    class England(People):
    def speak(self):
    print('说英国话') if __name__ == '__main__':
    # 多态的体现:功能或是需求,需要父类的对象,可以传入父类对象或任意子类对象
    # 注:一般都是规定需要父类对象,传入子类对象
    def ask_someone(obj):
    print('让%s上台演讲' % obj.name) # 父类提供,自己直接继承
    obj.speak() # 父类提供,只不过子类重写了 ch = Chinese('王大锤')
    en = England('Tom') # 传入Chinese | England均可以,因为都是People的一种状态(体现方式)
    ask_someone(ch)
    ask_someone(en) # 传入str不可以,因为str的对象没有name和speak
    # s = str('白骨精')
    # ask_someone(s)
    # p = People('kkk')

    鸭子类型:

  2. # 需求:需要一个对象,该对象有name属性及speak方法,就可以作为一种状态的体现被传入
    def ask_someone(obj):
    print('让%s上台演讲' % obj.name)
    obj.speak() # 鸭子类型:
    # 1.先规定:有什么属性及什么方法的类的类型叫鸭子类型
    # 2.这些类实例化出的对象,都称之为鸭子,都可以作为需求对象的一种具体体现
    class A:
    # 能有自己特有的属性和方法,可以和B完全不一样,但是必须有鸭子类型规定的属性和方法,不然就不是鸭子类型
    def __init__(self, name):
    self.name = name
    def speak(self):
    print('说AAAA') class B:
    # 能有自己特有的属性和方法,可以和A完全不一样,但是必须有鸭子类型规定的属性和方法,不然就不是鸭子类型
    def __init__(self, name):
    self.name = name
    def speak(self):
    print('说BBBB') ask_someone(B('B'))

day23--面向对象之封装、继承、多态的更多相关文章

  1. java面向对象(封装-继承-多态)

    框架图 理解面向对象 面向对象是相对面向过程而言 面向对象和面向过程都是一种思想 面向过程强调的是功能行为 面向对象将功能封装进对象,强调具备了功能的对象. 面向对象是基于面向过程的. 面向对象的特点 ...

  2. C# 面向对象基础&封装&继承&多态&加深一下冒泡排序写法

    (一)面向对象是什么? 面向对象是一种编程思想 (二)为什么要用面向对象? 1.结构清晰 2.易于维护 3.方便扩展 (三)new一个对象是什么过程? 实例化构造函数创建对象的过程就是将类实例化的过程 ...

  3. objective-c自学总结(三)---面向对象的封装,继承与多态

    面向对象的三大特性 封装 继承 多态 1.封装: 隐藏属性,方法或实现细节的过程称为封装 信息隐藏,隐藏对象的实现细节,不允许用户看到 将东西包装在一 然后以新的完整形式呈现出来 例如,两种或多种化学 ...

  4. php面向对象 封装继承多态 接口、重载、抽象类、最终类总结

    1.面向对象 封装继承多态  接口.重载.抽象类.最终类 面向对象 封装继承多态  首先,在解释面向对象之前先解释下什么是面向对象? [面向对象]1.什么是类? 具有相同属性(特征)和方法(行为)的一 ...

  5. Java基础——面向对象(封装——继承——多态 )

    对象 对象: 是类的实例(实现世界中 真 实存在的一切事物 可以称为对象) 类: 类是对象的抽象描述 步骤: 1.定义一个类 (用于 描述人:) ( * 人:有特征和行为) 2.根据类 创建对象 -- ...

  6. Python 入门 之 面向对象的三大特性(封装 / 继承 / 多态)

    Python 入门 之 面向对象的三大特性(封装 / 继承 / 多态) 1.面向对象的三大特性: (1)继承 ​ 继承是一种创建新类的方式,在Python中,新建的类可以继承一个或多个父类,父类又可以 ...

  7. python面向对象(封装,继承,多态)

    python面向对象(封装,继承,多态) 学习完本篇,你将会深入掌握 如何封装一个优雅的借口 python是如何实现继承 python的多态 封装 含义: 1.把对象的属性和方法结合成一个独立的单位, ...

  8. Python面向对象04 /封装、多态、鸭子类型、类的约束、super

    Python面向对象04 /封装.多态.鸭子类型.类的约束.super 目录 Python面向对象04 /封装.多态.鸭子类型.类的约束.super 1. 封装 2. 多态 3. 鸭子类型 4. 类的 ...

  9. 浅谈学习C++时用到的【封装继承多态】三个概念

    封装继承多态这三个概念不是C++特有的,而是所有OOP具有的特性. 由于C++语言支持这三个特性,所以学习C++时不可避免的要理解这些概念. 而在大部分C++教材中这些概念是作为铺垫,接下来就花大部分 ...

  10. Java三大特性(封装,继承,多态)

    Java中有三大特性,分别是封装继承多态,其理念十分抽象,并且是层层深入式的. 一.封装 概念:封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别:将抽象得到的数据 ...

随机推荐

  1. 【ASP.NET Core快速入门】(八)Middleware管道介绍、自己动手构建RequestDelegate管道

    中间件是汇集到以处理请求和响应的一个应用程序管道的软件. 每个组件: 可以选择是否要将请求传递到管道中的下一个组件. 之前和之后调用管道中的下一个组件,可以执行工作. 使用请求委托来生成请求管道. 请 ...

  2. vim编辑器详解(week1_day3)--技术流ken

    vi编辑器 作用:编辑文本文件中的内容的工具 命令历史 末行模式中,以:和/开头的命令都有历史纪录,可以首先键入:或/然后按上下箭头来选择某个历史命令. 启动vim 在命令行窗口中输入以下命令即可 v ...

  3. Spring Cloud Alibaba基础教程:支持的几种服务消费方式(RestTemplate、WebClient、Feign)

    通过<Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现>一文的学习,我们已经学会如何使用Nacos来实现服务的注册与发现,同时也介绍如何通过LoadBal ...

  4. 第35章 秘密(secrets) - Identity Server 4 中文文档(v1.0.0)

    在某些情况下,客户端需要使用身份服务器进行身份验证,例如 在令牌端点请求令牌的机密应用程序(也称为客户端) API在内省端点验证引用令牌 为此,您可以将秘密列表分配给客户端或API资源. 秘密解析和验 ...

  5. My操作小技巧

    1.当我们新增一条数据之后想要获取其自增长的id,可以紧随新增语句后调用 SELECT last_insert_id();即可获得,一般搭配变量一起使用 SELECT @newUserId:=last ...

  6. C#调用Oracle的存储过程时,连接字符串需要配置PLSQLRSet=1

    C#调用Oracle的存储过程时, 如果有个SYS_REFCURSOR的Output参数存储时, web.config文件中的连接字符串需要配置PLSQLRSet=1, 否则可能会报这个错:参数个数或 ...

  7. 结合JDK源码看设计模式——建造者模式

    概念: 将一个复杂对象的构建与它的表示分离.使得同样构建过程可以创建不同表示适用场景: 一个对象有很多属性的情况下 想把复杂的对象创建和使用分离 优点: 封装性好,扩展性好 详解: 工厂模式注重把这个 ...

  8. 对国内AR产业的预言

    先丢预言,国内任何AR公司,包含几大块,医疗行业.手机制造商和自动驾驶,倘若没有能力进行系统设计,最后都要死,或者裁掉业务. AR本身不会演化为独立的业务,而是作为辅助性的工具进入传统已经存在的部门之 ...

  9. java线程介绍

    文章讲解要点 1.线程创建几种方式2.线程常见设置方法,包括优先级.优先级休眠.停止等3.多线程间的数据交互与锁机制4.项目源码下载   线程介绍.png 一.线程创建方式 常见的线程创建方法以下三种 ...

  10. java.lang.NullPointerException一个低级的解决方法

    java.lang.NullPointerException 这次因为调用了类的方法的时候忘记了new对象了 导致该对象为空