python3_面向对象

2023-11-18

面向对象

OOP Object Oriented Programing
面向对象是认识世界的一种方法论, 一切皆对象
类class: 抽象的概念,一类具有共同特征的事物的集合;用计算机语言来描述,就是属性和方法的集合
实例instance: 类的一个实现
属性,是对象状态的抽象
方法,是对象行为的抽象

面向对象3要素:

  1. 封装
    隐藏数据:对外只暴露一些接口,只能通过接口访问对象
    组装:将数据和操作组装在一起
  2. 继承
    多继承少修改OCP(Open-closed Principle),使用继承来改变
  3. 多态
    动态绑定

命名上的一些约定

类名用大驼峰,类变量用全大写
变量名加下划线后缀, 避免与保留关键字冲突
变量名加下划线前缀, 表示变量非公有,
私有属性: 双下划线开头的属性名,对象属性字典中被改名_CLASS__ATTRIBUTE
私有方法: 双下划线开头的方法名,被解释器改名_CLASS_METHOD
单下划线前缀不带保护
前后双下滑线, 系统定义的变量, 避免定义

当使用__定义属性时,保存到属性字典中的key,变成_class__attr,class为定义属性语句所处的类
当使用.__attr 访问属性时,访问的其实是._class__attr,class为访问语句所处的类

类中的方法分类

0、也没有装饰, 没有参数的方法,实例不可调用(因为默认实例会作为参数会隐式传入),禁止使用
1、没有装饰器,至少有一个参数:self,即此方法被实例通过属性方式调用时,隐式传入实例本身,类对象调用时,就是普通函数,self占用一个参数位置
2、@classmethod 至少一个参数:cls,表示不管是类对象调用,还是实例调用,都隐式传入一个类对象本身,cls占用一个传参位,
常作为工厂函数,代替constructor,实例化一个需要不同参数的实例,例如rectangle 类实例化一个 square,只要一个参数 side_length
3、@staticmethod 可以没有参数,随意传参,不隐式传参

补丁:Monkey Pathch
运行时,对类的属性、方法进行动态替换,慎用,测试

把实例的属性保护起来,不让外部直接访问,外部使用getter方法访问,setter方法设置属性
属性装饰器 :property 常用来使属性read_only
@property;@method.setter;@method.deleter

Class Person:
    def __init__(self, name, age=18):
        self.name = name
        self.__age = age
    @property
    def age(self):
        return self.__age
    @age.setter
    def age(self, age):
        self.__age = age
    @age.deleter
    def age(self):
        del self.__age
tom = Person('Tom')
print(tom.age)  # getter
tom.age = 20     # setter
del tom.age       # deleter

Class Person:
    def __init__(self, name, age=18):
        self.name = name
        self.__age = age
    def getage(self):
        return self.__age
    def setage(self, age):
        self.__age = age
    def delage(slef):
        del self.__age
    age = property(getage, setage, delage, 'age property')

Class Person:
    def __init__(self, name, age=18):
        self.name = name
        self.__age = age
    age = property(lambda self: self.__age)  # getter

对象的销毁
def __del__(self): print('del')
类中可以定义__del__方法,称为析构函数(方法), 执行del命令时调用
当对象引用计数为0时, 自动调用

类的一些特殊属性和方法

__base__ 类的基类
__bases__ 类的基类元组
__mro__显示属性方法查找顺序 method resolution order,类的元组, mro() 调用
__subclasses__() :子类的列表

对象的属性和方法都可以使用.访问, 表示属性和对象发生了绑定
属性的访问顺序:实例自己的字典,实例所属类的字典,实例所属类的父类的字典
类中定义的属性(变量和方法)在外部看都变成了cls.attr或instance.attr,这里的外部包括类方法的内部,而在类的内部看还是attr
类的执行顺序,为从上到下,每一句都执行,语句块结束后才生成类
函数只做声明,调用时才执行
初始化函数init中,再实例化类,就会产生递归
类是语句块的最外层,只要类生成了,在当前modul中都可以访问到

继承和多态
继承加覆盖形成多态
override 覆盖
overload 重载, 例: type函数

super类,

def __init__(self, type1=None, type2=None)
super() -> same as super(__class__owner, self<first argument>)
super(type1) -> unbound super object
super(type1, obj) -> bound super object; requires isinstance(obj, type1)
super(type1, type2) -> bound super object; requires issubclass(type2, type1)
Typical use to call a cooperative superclass method:
class C(B):
    def meth(self, arg):
        super().meth(arg)
This works for class methods too:
class C(B):
    @classmethod
    def cmeth(cls, arg):
        super().cmeth(arg)

用super调用type1(第一个参数)的父类的方法(绑定或非绑定, 第二个参数),
用法: 子类的同名方法中调用父类的方法,达到增强方法的目的,类似装饰器
作为一个好的习惯,如果父类中定义了__init__方法,你就应该在子类的__init__中调用它

class A(B):
    def __init__(self,arg):
        super().__init__(arg)

Python2.2 之后引入共同祖先类object,为了兼容分为古典类(旧式类)和新式类
Python3 中全部都是新式类,新式类都继承自object,新式类可以使用super,使用超类方法

多继承

java中舍弃了多继承,java中一个类可以实现多个接口,一个接口可以继承多个接口,接口只有方法的声明
多继承可能带来二义性,解决二义性,要看深度优先还是广度优先
python3 解决多继承二义性使用C3算法,计算出一个MRO有序列表
尽量避免多继承

Mixin

定义Mixin类,只有特定方法的实现,其他类需要这些方法是,就继承Mixin类
多使用
Mixin体现的是一种组合的设计模式,多组合,把功能类独立出来复用
Mixin类的祖先类也应该是Mixin类

上下文管理

with object as foo:
    进入调用__enter__(self),return值赋给foo
    执行语句
    退出调用__exit__(exc_type, exc_value, exc_traceback),return 等效True 就压制异常

魔术方法

  • __dir__:
    dir()函数调用,如果没有提供,尽量收集对象的属性,对象 -> 类 -> 基类属性名全部收集, list实例没有__dict__属性,但用dir()可以找到它所有的的属性和方法
  • __init__, __del__:
    初始化,和销毁
  • __hash__:
    hash()调用,返回int,定义了这个方法,类的实例才可hash.
    字典,set用hash值做key,去重的话,要同时提供__eq__方法,来判断是否相同
    不定义虽然是hashable,但hash值不确定
  • __bool__:
    bool类实例化时调用,bool(),返回True or False,没有定义就找__len()__ ,长度非0即为True,len方法也没实现,默认是True,只有bool() -> False

    对象的特殊属性
    __name__ 标识符,字符串, 模块的name为A.B.C, 类名为C
    __module__ 所属module
    __class__ 实例的类,type()
    __bases__, __base__ 基类tuple, 基类
    __doc__ 文档
    __mro__ method resolution order, mro()调用
    __dict__ 属性字典
    __qualname__ 类的限定名, A.B.C

可视化
* __repr__:
repr()调用,返回对象的字符串表达,就按照object的定义,返回内存信息
* __str__:
str(),format(),print()调用,返回对象的字符串表达,没有定义,就去调用__repr__
* __int__: coverting object to built-in types
* __bytes__:
bytes(object)调用,返回对象的bytes表达,没有定义抛TypeError

运算符重载
operator_method(self, other)

  • __lt__,__le__,__eq__,__gt__,__ge__,__ne__
    <, <=, ==, >, >=, !=
  • __add__,__sub__,__mul__,__truediv__,__mod__,__floordiv__,__pow__,__divmod__,&__and__,|__or__,^__xor__
    都有对应的r方法,当第1个参数没有实现方法是,调用第2个参数的r方法.
  • __iadd__,__isub__,__imul__,__itruediv__,__imod__,__ifloordiv__,__ipow__:
    +=, -=, *=, /=, %=,/ /=, **=
    note: 比较大小,只要实现三种就可以,例<,<=,==,另外三种调用实现

容器相关方法
* __len__:
len()调用,返回对象长度(>=0的整数),没有定义报TypeError
* iter:
迭代对象时调用(for语句),返回一个新的迭代器对象,不能next()
* __contains__:
使用in成员运算符时调用,没有实现,就调用__iter__方法遍历,直到迭代找到为止
* __getitem__:
使用self[key]访问对象时调用
* __setitem__:
使用self[key] = value设置对象属性是调用
* __missing__:
字典或其子类使用self[key]访问时,key不存在时调用,拦截KeyError异常

可调用
* __call__:
实例被调用时调用

上下文管理

__exit__,__enter__:
with Point() as p:
同时实现两个方法,才属于上下文管理对象,enter进入与此对象相关的上下文时执行,exit退出与此对象相关的上下文时执行, 上下文管理是安全的,发生异常,__exit__依然执行

  • __enter__没有参数,返回值赋给as子句中的变量
  • __exit__有三个参数都与异常有关:exc_type,exc_value,traceback,如果返回等效True的值,压制异常,否则继续抛出异常
    上下文的应用场景:
    1. 增强功能
    2. 资源管理,打开资源就需要关闭,例如文件对象,网络连接,数据库连接
    3. 权限验证,在__enter__中处理

    • @contextlib.contextmanager装饰器,使一个函数具有上下文管理的功能,使用方法

      @contextlib.contextmanager
      def foo():
          print('enter')
          try:
              yield something # yield只能有一个,作为__enter__方法的返回值
          finally:
              print('exit')
      

反射reflection
指的是程序运行时获取定义信息,Python中,能够通过一个对象,找出其type, class, attribute, method的能力,称为反射或自省

  • 内建函数:
    • getattr(object, name[, default]):
      访问属性值,不存在则返回default,如果没有deault,抛出AttributeError, 调用的是__getattribute__
    • setattr(object, name, value):
      设置object属性值,存在则覆盖,不存在则新增,调用的__setattr__
    • hasattr(object, name):
      判断object是否存在名字为name的属性
    • delattr(self, name):
      删除对象属性,调用的是__delattr__
  • __setattr__:
    当尝试给属性赋值时调用,如果没有实现,object默认添加属性到对象的__dict__中.描述器例外.
  • __delattr__:
    删除对象属性时调用,如果不实现,object默认删除属性
  • __getattribute__:
    getattr(self,name) 和 self.attr 时调用
    如果没有实现,就执行object类的getattribute方法,即object.__getattribute__(self, name),即按照默认属性查找顺序查找,
    如果实现了同时又返回object.__getattribute__(self, name),则属性的查找顺序不变
    如果在其中抛出AttributeError,则调用__getattr__, 没有实现的话, 再抛AttributeError
  • __getattr__:
    访问对象的属性时,按照继承关系查找,查找失败要抛出AttributeE时调用,相当于设置默认值,如果没有实现,抛出AttributeError

描述器Descriptors

  • __get__, __set__, __delete__:
    签名如下:
    class A ;; class B;x=A() ;; b=B()
    __get__(self, instance, owner): B.x, b.x访问x时调用,B访问时,instance为None
    __set__(self, instance, value): b.x=value时调用
    __delete__(self, instance) :
    self是A的实例A(), instance是b, owner是B, value是设置的值
    如果一个类中实现了__get__, __set__, __delete__三个方法中的任何一个,就称为一个描述器类,这个类的实例作为另一个类的属性值时,
    如果仅实现了__get__, 就是非数据描述器 non-data descriptor
    如果同时实现了__set__, 就是数据描述器 data descriptor
    属性搜索__dict__先于非数据描述器,数据描述器先于__dict__,因为定义__set__后,设置属性值的时候都会调用__set__,而不是在__dict__中添加,即数据描述器绑定的属性行为不能被覆盖,而非数据描述器绑定的属性行为可以(通过__setattr__方法覆盖)
    描述器应用:classmethod,staticmethod,property装饰器
    描述器应用:flask作者写的网络工具werkzeug,实现缓冲器

槽位slots

  • __slots__ 明确的定义指定的属性,保护实例不被添加其他属性,阻止__dict__的自动创建
    应用场景: 实例在百万以上,实例属性简单,固定且不用动态增加,如列表节点,Poin等,使用__dict__可能会占用很大的空间
    私有属性可以被继承, __slots__ 继承不了
    使用__slots__
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python3_面向对象 的相关文章

随机推荐

  • (附源码)spring boot西安市中小学生护眼平台开发 毕业设计 080855

    springboot西安市中小学生护眼平台开发 摘要 俗话说 眼睛是心灵的窗户 可在这个科学技术日新月异发展的大千世界里 戴眼镜的人却随处可见 特别是我国在校学生3 2亿 平均近视率超过60 其中小学生为35 初中生为65 高中生达79 更
  • CAD螺纹lisp程序_公英制螺纹标注方法及加工大全

    普通螺纹的标记 螺纹公差带代号的标注在螺纹代号之后 中间用 分开 如果螺纹的中径公差带代号不同 则分别注出 前者表示中径公差带 后者表示顶径公差带 如果中径公差带与顶径公差带代号相同 则只标注一个代号 例如 M10 5g6g M10 1 6
  • shell是什么?ssh 与 git bash linux或cmd与 shell区别

    什么是shell Bash介绍及内容 1 认识Bash这个Shell 管理整个计算机硬件就是操作系统的内核 而内核是需要被保护的 不能让用户随便去修改不然系统崩溃了怎么办 所以一般用户只能通过Shell来跟内核沟通 shell的定义 什么是
  • ajax上传netcore插件,.NET Core Web 文件分片上传,带进度条实用插件

    git CMD命令 git initgit add 添加文件至暂存区 git commit m 描述性语句 随意写即可 git branch gh pages 创建仓库分支 git checkou 使用ARM模板部署自动扩展的Linux V
  • canvas圆形和正方形碰撞检测

    1 圆形碰撞检测 弧度转角度 function d2a n return n Math PI 180 角度转弧度 function a2d return n 180 Math PI window onload function let oC
  • 技术干货的选择性问题

    今天准备整理下微信的收藏夹 因为我发现好像在里面已经收藏了太多文章 这些收藏的文章并不是已经读过觉得不错故而收藏的 而是全没读过的 而其中的很大部份都是所谓的技术干货型文章 因为这类文章一方面比较长 另一方面比较费脑 所以我总是习惯在碰到的
  • 微软2013暑假实习生笔试题

    自己mark一下 以作后备 下面提交原文链接 原文博客 部分题目答案不确定 会持续更新 1 Which of the following calling convention s support s supportvariable leng
  • 报警服务器物理内存,从内存告警谈ESXi主机内存管理——内存构成

    在 如何处理ESXi主机的黄色告警 一文中我们提到了在没有冗余的管理网络或启用SSH的情况下 ESXi主机图标右下方将会出现黄色的告警 除了上述配置导致告警之外 另一种常见的告警就是ESXi主机的内存使用率过高 ESXi主机内存告警 当ES
  • osgEarth的Rex引擎原理分析(六十七)TileNode中的_surface(SurfaceNode)作用是什么

    目标 五十五 中的问题138 每个瓦片TileNode都有一个 surface SurfaceNode 这里面会存放瓦片的几何信息 drawable TileDrawable 这个几何信息会传给DrawTileCommand 用于绘制该瓦片
  • protobuf的安装使用

    简介 Protobuf是Protocol Buffers的简称 它是Google公司开发的一种数据描述语言 是一种轻便高效的结构化数据存储格式 可以用于结构化数据串行化 即序列化 它很适合做数据存储或 RPC 数据交换格式 可用于通讯协议
  • 转 使用Android Studio 创建第一个Android 应用

    转自 https blog csdn net u013926216 article details 81977815 一 使用Android Studio 开发Android 应用的流程 二 一个简单的登陆界面程序 程序功能说明 创建And
  • 有关win10的C:/ProgramFiles\WindowsApps\文件系统错误(12007)问题

    win10电脑开机的时候 突然出现这二个系统错误 C ProgramFiles WindowsApps b9eced6f asusbatteryhealthcharging 1 0 7 0 86 qmba6 以及 C ProgramFile
  • mysql 如何转换数据结构_如何将SQL查询结果转换为PANDAS数据结构?

    在这个问题上的任何帮助将不胜感激 所以基本上我想对我的SQL数据库运行查询并将返回的数据存储为Pandas数据结构 我已附上查询代码 我正在阅读有关Pandas的文档 但是在识别查询的返回类型时遇到了问题 我试图打印查询结果 但没有提供任何
  • 从零开始用C语言实现图片解码播放器(有源码)

    1 项目描述 1 1 项目硬件平台介绍 1 硬件平台 九鼎公司的X210开发板 S5PV210 Cortex A8内核 2 软件平台 linux2 6 35 7内核 直接基于linux API操作 1 2 项目功能介绍 1 调用编译好的可执
  • java---模块化

    模块的基本使用 模块的基本使用步骤 创建模块 按照以前的讲解方式创建模块 创建包 创建类 定义方法 为了体现模块的使用 我们创建2个模块 一个是myOne 一个是myTwo 在模块的src目录下新建一个名为module info java的
  • hard_socnet靶机(vulnhub)

    这个靶机的难度很高 慢慢摸索 接触新知识 首先这个靶机是2020 年的 我们如今2022年 2021出现了新的内核漏洞 CVE 2021 3493 我们这里可以利用 也成功了 但是 如果我们就在2020做此靶机怎么办呢 这里分享了两种打靶思
  • c#文件名去掉后缀_C# 怎么去掉文件名后缀

    public class test private static List getData String path List list new ArrayList lt gt try File f new File path File fs
  • FairGUI 坐标和Unity坐标转换

    一 FairGUI教程文档 https www bookstack cn read fairygui unity md 坐标系统 坐标原点 FairyGUI是以屏幕左上角为原点的 Unity的屏幕坐标是以左下角为原点的 一般这个转换都不需要
  • CNN卷积神经网络实现手写数字识别(基于tensorflow)

    1 1卷积神经网络简介 文章目录 1 1卷积神经网络简介 1 2 神经网络 1 2 1 神经元模型 1 2 2 神经网络模型 1 3 卷积神经网络 1 3 1卷积的概念 1 3 2 卷积的计算过程 1 3 3 感受野 1 3 4 步长和参数
  • python3_面向对象

    面向对象 魔术方法 描述器Descriptors 槽位slots 面向对象 OOP Object Oriented Programing 面向对象是认识世界的一种方法论 一切皆对象 类class 抽象的概念 一类具有共同特征的事物的集合 用