python中的类与对象

前言

在Python中,类是一种用于创建新类型对象的结构,它允许我们将数据和功能(属性和方法)封装到一个单独的逻辑单元中。类可以被看作是创建对象(实例)的蓝图或模板。类(Class)和对象(Object)是面向对象编程(OOP)的核心概念。

概念

类(Class)

类是一个用于创建对象的模板或蓝图。它定义了一组属性和方法,这些属性和方法将被它创建的对象所共享。类本质上是一种数据结构,它封装了数据以及操作这些数据的函数。

  • 属性:类中定义的变量。它们代表了该类所有对象共有的数据。
  • 方法:类中定义的函数。它们用于描述该类所有对象共有行为或功能。

通过定义一个类,你实际上是在定义一种新类型的数据结构,这种结构包含了特定类型、对象所具有的属性、可以对这些属性执行哪些操作。

对象(Object)

对象是根据类被创建出来的实例。每个对象都拥有独立于其他对象的属性值集合,但所有对象都共享同一个方法集合(即那些在其对应类中被定义过)。简单来说:

  • 每个实例对象都拥有从相同模板或蓝图(即:class)继承而来但独立存在、可以各自不同状态信息。
  • 实例化是根据类创建对象的过程

类与对象之间关系

  1. 类型与实例关系:从概念上讲,你可以把“class”看作“type”,把由此“type”生成出来具体存在事物看作“instance”。例如,“Dog”可以是一个表示所有狗通性特点模板名字;而你家那条叫做"Rex"具体小狗则可视作根据"Dog"模板生成出来、带有自己特定状态信息如年龄、品种等信息记录项事物。
  2. 共享与唯一性原则:所有由同一个class生成出来instances会共享该class定义的代码逻辑项,不随各自instance状态变化而变化;同时每个instance也会拥有属于自己唯一且可能随时间改变状态信息记录项。
  3. 继承性原则: 类之间可以通过继承机制分享通用代码逻辑项,并允许子级别class在保持父级别已经提供功能基础上添加或修改部分以满足更加具体需求场景使用要求。

类定义

一个基本的类定义包括关键字class,后面跟着类名和冒号。在其下方缩进的代码块中,可以定义属性(变量)和方法(函数)。

要使用一个类,你需要根据该类创建对象。每个对象都会有自己独立的属性集合。

class MyClass:def __init__(self, value):  # 特殊方法__init__用于初始化对象,构造器self.my_attribute = valuedef my_method(self):return self.my_attribute * 2# 实例化对象
obj = MyClass(99)
print(obj)
print(obj.my_method())
print(obj.my_attribute)# 直接修改对象的属性
obj.my_attribute = 100print(obj)
print(obj.my_method())
print(obj.my_attribute)

类的命名规范

  1. 驼峰命名法:Python中的类名通常使用驼峰命名法(CamelCase)。这意味着类名中每个单词的首字母都大写,而且单词之间不使用下划线分隔。例如,MyClassDataProcessorCarEngine

  2. 描述性命名:类名应该简洁且富有描述性,清楚地表明类的用途或功能。例如,避免使用模糊的名称如FooBar,而应选择更具描述性的名称,如CustomerEmailParser

  3. 避免缩写:尽量避免使用缩写,因为缩写可能会使代码的可读性降低。完整的单词能更好地表达类的意图和功能。

  4. 首字母大写:按照Python的约定,类名的首字母应该大写,即使它是一个缩写。例如,URLParser而不是urlParser

  5. 避免使用内置类型名称:避免使用像strlistdict这样的Python内置类型名称作为类名,以免造成混淆。

  6. 命名长度:虽然没有硬性的长度限制,但一般推荐类名不要过长,以保持代码的清晰和易于维护。

特殊方法

Python提供了多个特殊方法(也称为魔术方法),它们由双下划线包围。这些特殊方法提供了与Python语言功能集成的方式。

初始化和构造

  • __init__(self, [...]): 对象初始化方法,在创建新实例后被调用。
  • __new__(cls, [...]): 实际的对象构造函数,是一个静态方法,在__init__之前被调用。
class TestClassMethod:# 定义变量,如果不赋值则必须指定类型# 但是类型注解 value_a: int 表示期望 value_a 是一个整数类型,但它并不会阻止你将其他类型赋给该属性。value_a: intvalue_b = "value_b"# 初始化方法def __init__(self, init_value: int):  # 类型注解本身并不会强制变量类型,在运行时仍然可以给带有类型注解的变量赋予任何类型的值。print(f'初始化方法调用... init_value : {init_value}')# 如果不指定 self. 则为局部变量,无法在这里赋值# value_a = init_valueself.value_a = init_value# 实际的对象构造函数,是一个静态方法,在__init__之前被调用。# 在生产环境编写代码时通常不需要自己手动重写 __new__ 方法;除非你需要控制对象创建过程。对于大多数情况,默认行为已经足够。@staticmethod# 名为 __new__ 的实例方法并非特殊方法。特殊方法 __new__ 应当被定义为静态方法(使用装饰器 @staticmethod),或者更常见地作为类方法(使用装饰器 @classmethod)。def __new__(cls, *args, **kwargs):print(f'对象构造函数调用... cls : {cls}')return super(TestClassMethod, cls).__new__(cls)method = TestClassMethod(1)print(method.value_a)
# 虽然类中定义了类型为int,但是照常可以赋值字符串
method.value_a = 'aa'
print(method.value_a)print(method.value_b)print(dir(method))

表示和格式化

  • __repr__(self): 定义对象的“官方”字符串表示。
  • __str__(self): 定义对象的“非正式”或可打印字符串表示。
  • __format__(self, format_spec): 定义当使用format()函数时对象的格式。
__repr__(self)
  • 目的:创建一个代表对象的官方字符串表示形式。
  • 调用时机:当你调用内置函数repr()时;当没有定义__str__时,在使用print函数打印对象或者在解释器中直接输入变量名查看对象时;还有就是在调试过程中经常会看到这个表示。
  • 特点:应该尽可能返回一个明确且不模糊的字符串表示形式,最好能够通过这个字符串来重新创建该对象。因此,通常返回值会看起来像是一个有效的Python表达式。
class Point:def __init__(self, x, y):self.x = xself.y = ydef __repr__(self):return f"Point({self.x}, {self.y})"
__str__(self)
  • 目的:创建一个对用户友好(非技术用户)的字符串表示形式。
  • 调用时机:当你使用内置函数str()或者使用print函数打印一个对象时。
  • 特点:返回值应该是可读性强、信息友好型描述。
class Point:def __init__(self, x, y):self.x = xself.y = ydef __str__(self):return f"Point located at ({self.x}, {self.y})"
区别

虽然两者都提供了关于对象信息展示方式,但主要区别在于目标受众和它们各自所承担角色:

  • __repr__: 面向开发者和调试器。其目标是明确无误地表达出如何构造出相同数据内容的新实例。
  • __str__: 面向最终用户。其目标是提供友好易懂且便于阅读理解信息。

如果只实现了其中之一,则未实现者将默认使用已实现者进行替代。如果都没有实现,则会默认使用继承自object类中相应方法。

建议至少定义一个__repr__() 方法,在大多数情况下它将足够用来输出有意义并可辨识资源信息,并作为后备方案以防未定义 __str__().

运算符重载(算术、比较运算符)

  • __add__(self, other): 加法运算符+
  • __sub__(self, other): 减法运算符-
  • __mul__(self, other): 乘法运算符*
  • __truediv__(self, other): 真除法运算符/.
  • __floordiv__(self, other): 地板除法运算符//.
  • __mod__(self, other): 取模(余数)操作 %.
  • __eq__(self, other): 等于操作=.
  • __ne__(self, other): 不等于操作不等于操作.
class TestClassMethod:value = 100def __add__(self, other):return self.value + otherdef __sub__(self, other):return self.value - otherdef __mul__(self, other):return self.value * otherdef __truediv__(self, other):return self.value / otherdef __floordiv__(self, other):return self.value // otherdef __mod__(self, other):return self.value % otherdef __eq__(self, other):return self.value == otherdef __ne__(self, other):return self.value != other# 大于def __gt__(self, other):return self.value > other# 大于等于def __ge__(self, other):return self.value >= other# 小于def __lt__(self, other):return self.value < other# 小于等于def __le__(self, other):return self.value <= othermethod = TestClassMethod()print(method + 100)
print(method - 100)
print(method * 100)
print(method / 100)
print(method // 100)
print(method % 100)
print(method == 100)
print(method != 100)
print(method > 100)
print(method >= 100)
print(method < 100)
print(method <= 100)

属性访问

属性访问相关的特殊方法可以帮助我们自定义属性的获取、设置和删除行为:

class TestClassMethod:def __getattr__(self, name):# 当尝试获取一个不存在的属性时调用print(f"【报错】!!尝试获取不存在的属性: {name} ")return '不存在的属性!'def __setattr__(self, name, value):# 当对属性赋值时调用print(f"调用赋值方法 {name} {value}")# self.name = value 不能这样赋值,会导致递归调用super().__setattr__(name, value)def __delattr__(self, name):# 当删除一个属性时调用print(f"调用删除属性的方法 {name} ")super().__delattr__(name)method = TestClassMethod()method.value = 1
print(method.value)
print(method.value2)
del method.value

类属性

在Python中,类的属性可以分为两种:类属性和实例属性。

类属性

  1. 类属性访问
    • 类属性可以通过类名直接访问。
    • 实例也可以访问类属性,但是如果实例具有与类属性同名的实例属性,则会优先访问实例属性。
  2. 修改类属性
    • 通过类名修改类属性会影响到所有访问该属性的实例,因为它们共享同一个类变量。
    • 如果通过实例修改看似“修改”了一个类变量(即instance.attribute = value),其实是在该实例中创建了一个同名的实例变量,并不会影响到其他实例或者是该变量在原来的那个class中。

类属性是属于类本身的变量,它被所有该类的实例共享。这意味着如果你修改了一个类的类属性,这个改变会影响到所有该类的实例。

class MyClass:class_attribute = 0# 修改类属性将影响所有实例
MyClass.class_attribute = 1instance1 = MyClass()
instance2 = MyClass()print(instance1.class_attribute)  # 输出: 1
print(instance2.class_attribute)  # 输出: 1

实例(对象)属性

实例属性是属于特定对象(即某个具体实例)的变量。每个对象都有自己独立的一套实例属性,修改一个对象的实例属性不会影响其他对象。

  1. 对象属性访问
    • 对象属性只能通过实例对象访问。它们是绑定到特定实例的,因此每个实例都有自己独立的对象属性副本。
  2. 修改对象属性
    • 对象属性的修改仅限于该特定实例。修改实例的属性不会影响到类的其他实例。
    • 如果尝试通过实例修改一个不存在的属性,Python会自动在该实例上创建这个属性。
class MyClass:def __init__(self, value):self.instance_attribute = value# 每个对象都有自己独立的 instance_attribute 属性。
instance1 = MyClass(10)
instance2 = MyClass(20)print(instance1.instance_attribute)  # 输出: 10
print(instance2.instance_attribute)  # 输出: 20# 修改一个对象的 instance_attribute 不会影响另一个。
instance1.instance_attribute = 30print(instance1.instance_attribute)  # 输出: 30
print(instance2.instance_attribute)  # 输出: 20

属性引用和修改规则

  • 类变量属于整个类,所有基于此类创建出来的对象共享这个变量。
  • 如果需要对所有对象都生效地更改某个值,请操作这个值所属类上定义好了的那个变量。
  • 对象属性是绑定到类的实例上的,因此它们对于每个实例来说都是唯一的。
  • 修改一个实例的属性不会影响到其他实例。
  • 通过实例可以访问类属性,但是如果实例有一个与类属性同名的对象属性,则访问的是对象属性,这体现了Python中的“名称遮蔽”特性。(在Python中,“名称遮蔽”(Name Shadowing)是指子作用域中的名称覆盖了外部作用域中相同名称的变量。这种特性在类属性与实例属性之间的交互中尤为常见。)
class TestClassModifyAttr:attribute = 0def __init__(self, value):self.attribute = value@propertydef test_method(self):"""当你尝试访问或者修改一个对象(即某个具体实例)上不存在但在其对应类型定义中存在作为`@property`装饰器修饰过得方法时,Python解释器将调用相应方法来处理此次访问或者修改行为。"""print("调用 test_method")a = TestClassModifyAttr(999)print(a.attribute)
print(a.test_method)# 如果你尝试访问或者修改一个不存在于任何地方(既不是该类型定义中也不是其基类型定义中)
# 且未通过`@property`装饰器修饰过得方法时,
# 则解释器将调用 `__getattr__()` 或 `__setattr__()` 特殊方法来处理此次访问或者修改行为。
print(a.test_method2)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/758574.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM学习-类加载

目录 1.类文件结构 2.类加载器 3.类加载的三个阶段 3.1加载 3.2链接 3.2.1验证 3.2.2准备阶段 3.2.3解析阶段 3.3初始化 4.拓展&#xff1a;反射 4.1获取类对象 4.2创建实例 4.3获取方法 4.4方法调用 1.类文件结构 2.类加载器 类加载器用来将类文件的二进制字节码加载到JV…

猜数字游戏有三变(Java篇)

本篇会加入个人的所谓‘鱼式疯言’ ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

小白学视觉 | 超详细!Python中 pip 常用命令

本文来源公众号“小白学视觉”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;超详细&#xff01;Python中 pip 常用命令 相信对于大多数熟悉Python的人来说&#xff0c;一定都听说并且使用过pip这个工具&#xff0c;但是对它的了…

中国联通推出了一站式全流程的专业安全服务

中国联通依托多年深耕通信与信息安全领域的丰富经验和专业技术积累&#xff0c;推出了一站式全流程的专业安全服务&#xff0c;从网络环境的前期准备阶段直至正式运行&#xff0c;均提供全面、立体、高效的保障措施&#xff0c;确保各类企事业单位在网络空间的安全稳定。 请点击…

算法打卡day23|回溯法篇03|Leetcode 39. 组合总和、40.组合总和II、131.分割回文串

算法题 Leetcode 39. 组合总和 题目链接:39. 组合总和 大佬视频讲解&#xff1a;组合总和视频讲解 个人思路 这道组合题主要是有总和的限制&#xff0c;当递归和超过了总和就return&#xff0c;递归时加上回溯去遍历数组。 解法 回溯法 把组合问题抽象为如下树形结构 如上…

【通信原理笔记】【二】随机信号分析——2.5 高斯随机过程

文章目录 前言一、高斯分布二、高斯过程三、高斯白噪声四、窄带高斯白噪声的复包络总结 前言 这篇我们来学习通信原理中非常重要的高斯&#xff08;正态&#xff09;随机过程&#xff0c;在之后的内容中会反复使用这个模型 一、高斯分布 首先回顾一下概率论中学过的高斯分布的…

达源电机超高速数码马达震撼来袭

新质生产力是什么? 12万转高速电吹风机马达引领行业技术革新 随着科技的不断进步&#xff0c;电吹风机行业正迎来一场深刻新质生产力技术革新。在这场革新中&#xff0c;达源电机以其独特绕线技术与自适应平衡磁场的马达技术&#xff0c;成功打破了国外高速马达电机悬臂梁专利…

uniapp——第3篇:自定义组件、组件间传数据

前提&#xff0c;建议先学会前端几大基础&#xff1a;HTML、CSS、JS、Ajax&#xff0c;还有一定要会Vue!&#xff08;Vue2\Vue3&#xff09;都要会&#xff01;&#xff01;&#xff01;不然不好懂 一、组件是啥玩意&#xff1f; 我之前讲vue2的文章讲过 Vue全家桶:vue2vue3全…

位图与布隆过滤器

目录 一、位图 1、问题用位图来解决&#xff1a; 二、 布隆过滤器 1、将哈希与位图结合&#xff0c;即布隆过滤器 2.布隆过滤器的查找 3.布隆过滤器的删除 4.布隆过滤器优点 5、布隆过滤器缺陷 三、海量数据处理问题&#xff1a; 一、位图 问题1&#xff1a;给40亿个不…

netron:本地查看服务器端打开的onnx文件

我们开发一般都在服务器中开发&#xff0c;假如我们在服务器端导出了一个onnx文件&#xff0c;不将onnx文件传到本地&#xff0c;如何进行本地查看呢&#xff1f; netron --port 8082 --host 10.75.29.201 model_data/deeplab_0131.onnx--host : 指定服务器的ip, 注意不是本地…

2024/03/19(网络编程·day5)

一、思维导图 二、selec函数实现TCP并发服务器 #include<myhead.h>#define SER_PORT 8888 //服务器端口号 #define SER_IP "192.168.117.116" //服务器IP int main(int argc, const char *argv[]) {//1、创建一个套接字int sfd -1;sfd socket(AF_INET,SOC…

软件设计师:03 - 数据库系统

一、数据模型的分类 1.1、概念数据模型 1.2、结构数据模型 1.3 真题 二、三级模式 概念模式对应的是基本表&#xff0c;概念模式也称为模式 外模式对应的是视图&#xff0c;也称用户模式或者子模式 内模式对应的是数据库里面的存储文件&#xff0c;也称存储模式 真题 三、两级…

VO、RVO、ORCA(动态避障)算法

碰撞锥&#xff08;碰撞区域&#xff09; 上上图中假设B物体处于静止状态&#xff0c;A物体沿着向量v1和v2移动&#xff0c;刚好能和B擦肩而过&#xff0c;不会发生碰撞&#xff1b;若V1和V2的夹角再小一点的话就一定会发生碰撞。此时会产生碰撞区域&#xff1a; 红线画出来…

蓝桥杯练习04学生成绩统计

学生成绩统计 介绍 随着大数据的发展&#xff0c;数据统计在很多应用中显得不可或缺&#xff0c;echarts作为一款基于JavaScript的数据可视化图表库&#xff0c;也成为了前端开发的必备技能&#xff0c;下面我们一起来用echarts开发一个学生数据统计的柱形图。 准备 开始答…

Vmware使用ubuntu报错空间不够

Vmware使用ubuntu报错空间不够 1.vmware修改2.进入镜像进行修改2.1需要下载GParted软件 1.vmware修改 这个需要把硬盘的大小进行扩展 2.进入镜像进行修改 2.1需要下载GParted软件

C++_回文串

目录 回文子串 最长回文子串 分割回文串 IV 分割回文串 II 最长回文子序列 让字符串成为回文串的最少插入次数 回文子串 647. 回文子串 思路&#xff0c;i j表示改范围内是否为回文串&#xff0c; ②倒着遍历是为了取出dp[i 1][j - 1] ③i j 只有一对&#xff0c;不会重复…

C++模版(一)

C++模版 概念函数模版函数模版语法注意事项普通函数和函数模版区别普通函数和函数模版的调用规则模版的局限性具体化模版本质分析概念 模版也可称之为泛型,可以理解为模具,通过模具可以创建多种实现,大大提高了复用性。 实际生活中,有很多模版的例子。比如我们的入职简历,…

harmonyOS简介及背景

harmonyOS的场景模式18n: 1&#xff08;入口手机&#xff09;8&#xff08;电脑、VR、手环、iPad、智慧屏、&#xff09;–wifi—n(车载、智能家居等所有)harmonyOS不需要考虑软硬件的差异&#xff0c;是一个兼容N种的超级终端harmonyOS干了两件事&#xff1a; &#xff08;1&a…

施工升降机AI数人数识别摄像机

施工现场作为一个复杂的工作环境&#xff0c;在施工过程中通常会有大量的人员出入&#xff0c;为了确保施工安全和管理效率&#xff0c;近年来施工升降机AI数人数识别摄像机应运而生。 这种摄像机依靠先进的人工智能技术和摄像头设备&#xff0c;能够实时监测和识别施工升降机内…

AIGC——ComfyUI工作流搭建、导入与常用工作流下载

工作流 ComfyUI工作流是一个基于图形节点编辑器的工作流程&#xff0c;通过拖拽各种节点到画布上&#xff0c;连接节点之间的关系&#xff0c;构建从加载模型到生成图像的流程。每个节点代表一个与Stable Diffusion相关的模型或功能&#xff0c;节点之间通过连线传递图片信息。…