Python 类对象
Python 类对象
经典迭代器
-
可迭代对象的定义: 使用内置的iter可以获取迭代器的对象。如果对象实现了能返回迭代器的
__iter__
方法,那么对象就是可迭代的。序列都可以迭代。实现了__getitem__
方法,而且接受从0开始的索引,这种对象也是可以迭代的。 -
可迭代对象与迭代器之间的关系:Python从可迭代对象中获取迭代器。
import re
import reprlibRE_WORD = re.compile(r'\w+')class SentenceV2:def __init__(self, text):self.text = textself.words = RE_WORD.findall(text)def __repr__(self):return f'Sentence({reprlib.repr(self.text)})'def __iter__(self):# 返回一个迭代器return SentenceIterator(self.words)class SentenceIterator:def __init__(self, words):self.words = words # 初始化索引self.index = 0def __next__(self):try:word = self.words[self.index]except IndexError:raise StopIteration()self.index += 1return worddef __iter__(self): return self
- 可迭代对象有一个
__iter__
方法,每次都实例化一个新迭代器。 - 迭代器要实现
__next__
方法,返回单个元素,此外还要实现__iter__
方法,返回迭代器本身。 - 迭代器也是可迭代对象,但是可迭代对象不是迭代器。
生成器函数
import re
import reprlibRE_WORD = re.compile(r'\w+')class SentenceV3:def __init__(self, text):self.text = textself.words = RE_WORD.findall(text)def __repr__(self):return 'Sentence(%s)' % reprlib.repr(self.text)def __iter__(self):for word in self.words:# 产生当前的wordyield wordclass ArithmeticProgression:def __init__(self, begin, step, end=None):self.begin = beginself.step = stepself.end = end # None -> "infinite" seriesdef __iter__(self):result_type = type(self.begin + self.step)result = result_type(self.begin)forever = self.end is Nonewhile forever or result < self.end:yield resultresult += self.step
只要Python函数的主体中有yield
关键字,该函数就是生成器函数。调用生成器函数,返回一个生成器对象。
生成器工作原理:
- 生成器函数创建一个生成器对象,包装生成器函数的主体。
- 把生成器对象传给
next()
函数时,生成器函数提前执行函数主体中的下一个yield
语句,返回产出的值,并在函数主体的当前位置暂停。 - 函数的主体返回时,Python创建的外层生成器对象抛出
StopIteration
异常。
上下文管理器
import sysclass LookingGlass:def __enter__(self):self.original_write = sys.stdout.write# 打上猴子补丁sys.stdout.write = self.reverse_writereturn 'JABBERWOCKY'def reverse_write(self, text):# 反转参数的内容self.original_write(text[::-1])def __exit__(self, exc_type, exc_value, traceback):# 将原来的方法还原sys.stdout.write = self.original_writeif exc_type is ZeroDivisionError:print('Please DO NOT divide by zero!')return True
Vector2d
from array import array
import math class Vector2d: typecode = 'd' def __init__(self, x, y): self.x = float(x) self.y = float(y) # 可以解包 v = Vector2d(2,2)# x,y = vdef __iter__(self): return (i for i in (self.x, self.y)) # print返回def __repr__(self): class_name = type(self).__name__ return '{}({!r}, {!r})'.format(class_name, *self) def __str__(self): # 调用__iter__return str(tuple(self)) def __bytes__(self): return (bytes([ord(self.typecode)]) + bytes(array(self.typecode, self))) # 判断Vector2d是否相等def __eq__(self, other): return tuple(self) == tuple(other) def __abs__(self): return math.hypot(self.x, self.y)def __bool__(self): return bool(abs(self))
格式化显示
>>> format(42, 'b')
'101010'
>>> format(2 / 3, '.1%')
'66.7%'
# datetime类重构了__format__方法
>>> from datetime import datetime
>>> now = datetime.now()
>>> format(now, '%H:%M:%S')
'18:49:05'
>>> "It's now {:%I:%M %p}".format(now)
"It's now 06:49 PM"
def __format__(self, fmt_spec=''): components = (format(c, fmt_spec) for c in self) return '({}, {})'.format(*components)
>>> v1 = Vector2d(3, 4)
>>> format(v1)
'(3.0, 4.0)'
>>> format(v1, '.2f')
'(3.00, 4.00)'
>>> format(v1, '.3e')
'(3.000e+00, 4.000e+00)'
可哈希的
为了把 Vector2d 实例变成可哈希的,必须实现 hash 方法 (还需要 eq 方法,前面已经实现了)。此外,还要让向量实例 不可变
class Vector2d: typecode = 'd' def __init__(self, x, y): self.__x = float(x) self.__y = float(y) @property def x(self): return self.__x @property def y(self): return self.__y def __hash__(self): return hash((self.x, self.y))
使用 slots 节省空间
默认情况下,Python 把各个实例的属性存储在一个名为 dict 的字典中字典消耗的内存很多。但是,如果定义一个名为 slots 的类属性,以序列的形式 存储属性名称,那么 Python 将使用其他模型存储实例属性: slots 中的属性名称存储在一个隐藏的引用数组中,消耗的内 存比字典少。
>>> class Pixel:
... __slots__ = ('x', 'y')
...
>>> p = Pixel()
>>> p.__dict__
Traceback (most recent call last): ...
AttributeError: 'Pixel' object has no attribute '__dict__'
>>> p.x = 10
>>> p.y = 20
# 不允许添加其他属性
>>> p.color = 'red'
Traceback (most recent call last): ...
AttributeError: 'Pixel' object has no attribute 'color'
Vector
多维向量
>>> Vector([3.1, 4.2])
Vector([3.1, 4.2])
>>> Vector((3, 4, 5))
Vector([3.0, 4.0, 5.0])
>>> Vector(range(10))
Vector([0.0, 1.0, 2.0, 3.0, 4.0, ...])
from array import array
import reprlib
import math class Vector: typecode = 'd' def __init__(self, components): self._components = array(self.typecode, components) def __iter__(self): return iter(self._components) def __repr__(self): # 替换为省略号# 返回array('d', [0.0, 1.0, 2.0, 3.0, 4.0, ...])components = reprlib.repr(self._components) components = components[components.find('['):-1] return f'Vector({components})' def __str__(self): return str(tuple(self)) def __bytes__(self): return (bytes([ord(self.typecode)]) + bytes(self._components)) # 调用len()返回def __len__(self): return len(self._components) def __eq__(self, other): if len(self) != len(other): return False for a, b in zip(self, other): if a != b: return False return True def __abs__(self): return math.hypot(*self) def __bool__(self): return bool(abs(self))
切片
def __getitem__(self, index): return self._components[index]
>>> v1 = Vector([3, 4, 5])
>>> len(v1)
3
>>> v1[0], v1[-1]
(3.0, 5.0)
>>> v7 = Vector(range(7))
# 返回的是array
>>> v7[1:4]
array('d', [1.0, 2.0, 3.0])
def __getitem__(self, key): # 调用Vector[a:b:c] 传入的是slice(a,b,c)if isinstance(key, slice): cls = type(self) return cls(self._components[key]) # 调用Vector[a]index = operator.index(key) return self._components[index]
动态存取属性
# 希望xyzt能获取前4个元素
>>> v = Vector(range(10))
>>> v.x
0.0
>>> v.y, v.z, v.t
(1.0, 2.0, 3.0)
__match_args__ = ('x', 'y', 'z', 't') def __getattr__(self, name): cls = type(self) try: pos = cls.__match_args__.index(name) except ValueError: pos = -1 if 0 <= pos < len(self._components): return self._components[pos] msg = f'{cls.__name__!r} object has no attribute {name!r}' raise AttributeError(msg)
>>> a = Vector(range(9))
>>> a
Vector([0.0, 1.0, 2.0, 3.0, 4.0, ...])
>>> a.x
0.0
>>> a.y
1.0
# x不应该可以直接复制,这样会创建一个x变量
>>> a.x = 10
>>> a
Vector([0.0, 1.0, 2.0, 3.0, 4.0, ...])
>>> a.x
10
>>>
# 赋值操作def __setattr__(self, name, value): cls = type(self) if len(name) == 1: if name in cls.__match_args__: error = 'readonly attribute {attr_name!r}' elif name.islower(): error = "can't set attributes 'a' to 'z' in
{cls_name!r}" else: error = '' if error: msg = error.format(cls_name=cls.__name__,
attr_name=name) raise AttributeError(msg) # 没问题就调用父类方法super().__setattr__(name, value)
哈希
def __hash__(self): hashes = (hash(x) for x in self._components) # reduce类似于递归函数,sum、any 和 all的本质都是调用reducereturn functools.reduce(operator.xor, hashes, 0)
msg = error.format(cls_name=cls.__name__,
attr_name=name)
raise AttributeError(msg)
# 没问题就调用父类方法
super().setattr(name, value)
### 哈希```pythondef __hash__(self): hashes = (hash(x) for x in self._components) # reduce类似于递归函数,sum、any 和 all的本质都是调用reducereturn functools.reduce(operator.xor, hashes, 0)
相关文章:

Python 类对象
Python 类对象 经典迭代器 可迭代对象的定义: 使用内置的iter可以获取迭代器的对象。如果对象实现了能返回迭代器的__iter__方法,那么对象就是可迭代的。序列都可以迭代。实现了__getitem__方法,而且接受从0开始的索引,这种对象也…...
pytest unittest temp path单元测试创建临时文件
参考了这个:Test Files Creating a Temporal Directory in Python Unittests | Simple IT 🤘 Rocks 并使用pathlib做了优化: import tempfile import unittest from pathlib import Pathclass TestExample(unittest.TestCase):def test_exa…...

在线样机生成器,制作精美的电脑手机壁纸图片展示
在线样机生成器,可以制作精美的电脑手机壁纸图片展示。在线样机生成器支持不同的模型如浏览器、手机、笔记本电脑、手表等结合使用,帮助用户快速生成样机展示图片。下面小编就来和大家分享一款免费的在线样机生成器-壁纸样机生成器。 壁纸样机生成器是一…...

FreeRTOS实时操作系统
1.认识实施操作系统 1.1 裸机和实时操作系统 裸机: 早期嵌入式开发没有嵌入式操作系统的概念,直接操作裸机,在裸机上写程序,比如用51单片机基本就没有操作系统的概念。 通常把程序设计为前后台系统,主要分为两部分&a…...

C/S、B/S架构(详解)
一、CS、BS架构定义 CS架构(Client-Server Architecture)是一种分布式计算模型,其中客户端和服务器之间通过网络进行通信。在这种架构中,客户端负责向服务器发送请求,并接收服务器返回的响应。服务器则负责处理客户端的…...
代码随想录算法训练营第六十五天|KM99. 岛屿数量——深搜、KM99. 岛屿数量——广搜、KM100. 岛屿的最大面积
代码随想录算法训练营第六十五天 KM99. 岛屿数量——深搜 题目链接:KM99. 岛屿数量 使用递归深度搜索,将每次遇到的岛屿上下左右记录为已经到过,如果遇到没到过的说明它上下左右不是之间遍历过的岛屿,结果计数1。最后统计计数即…...
Lua 面向对象编程
Lua 面向对象编程 Lua 是一种轻量级的编程语言,通常用于嵌入应用程序中,提供灵活的扩展和定制功能。尽管 Lua 本身是一种过程式语言,但它提供了强大的元机制,允许开发者实现面向对象的编程范式。本文将探讨 Lua 中的面向对象编程(OOP)概念、实现方式以及最佳实践。 面向…...

AI赋能前端:你的Chrome 控制台需要AI(爱)
像会永生那样去学习,像明天就要死亡那样去生活。——圣雄甘地 大家好,我是柒八九。一个专注于前端开发技术/Rust及AI应用知识分享的Coder 此篇文章所涉及到的技术有 AI(Gemini)ChromeDevTool🪜魔法接码平台因为,行文字数所限,有些概念可能会一带而过亦或者提供对应的学习…...

代码随想录-Day38
509. 斐波那契数 斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) 0,F(1) 1 F(n) F(n - 1) F(n - 2),其中 …...

CSS阴影优化气泡框样式
<body> <div class"pop">气泡框</div> </body>body{display: flex;justify-content: center;align-items: center;height: 100% } .pop{display: flex;justify-content: center;align-items: center;background: #409eff;width: 150px;heigh…...

强化安全新篇章:韶关石油化工可燃气体报警器年检解析
韶关,这座位于广东省北部的城市,近年来在石油化工行业取得了显著的发展。 随着一批批大型石化企业的进驻和投产,韶关不仅成为了区域性的石化产业基地,也为地方经济带来了强劲的增长动力。 然而,随着石化产业的快速发…...
Centos7 Docker部署PgSQL
拉取镜像 docker pull postgres:14.7运行容器 docker run --restartalways --nethost --shm-size"2g" --name pgsql -v /home/postgresql/data/pgdata:/var/lib/postgresql/data -v /etc/localtime:/etc/localtime -e POSTGRES_PASSWORDtest2023 -d postgres:14…...
LeetCode:经典题之21、24 题解及延伸
系列目录 88.合并两个有序数组 52.螺旋数组 567.字符串的排列 643.子数组最大平均数 150.逆波兰表达式 61.旋转链表 160.相交链表 83.删除排序链表中的重复元素 389.找不同 1491.去掉最低工资和最高工资后的工资平均值 896.单调序列 206.反转链表 92.反转链表II 141.环形链表 …...
【C++11】initializer_list详解!
一、什么是initializer_list? nitializer_list 是一种C11新的类型特性,它允许我们以统一的方式初始化对象。它是一个代表数组的轻量级包装器,通常用于构造函数和函数参数中,以允许传递一个初始化元素列表。 initializer_list也是一种模板类…...
如何在Java中处理UnsupportedOperationException异常?
如何在Java中处理UnsupportedOperationException异常? 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 在Java编程中,我们经常会遇到各…...

WPS没保存关闭了怎么恢复数据?4个方法(更新版)
想象一下,你正在用WPS奋笔疾书,灵感如泉水般涌出,突然间,电脑却跟你开了个玩笑——啪地一下,文档未保存就关闭了!是不是感觉像是被泼了一盆冷水,所有的热情瞬间熄灭?别急,…...

elementplus el-table(行列互换)转置
Element Plus v2.4.0, repl v3.4.0 <template> <div><el-table :data"tableData" style"width: 100%"><el-table-column prop"name" label"名字" width"180" /><el-table-column prop"wei…...

Gradle 核心之 Task
一、前言 只有 Task 才可以在 Gradle 的执行阶段去执行(其实质是执行的 Task 中的一系列 Action),所以 Task 的重要性不言而喻。 二、Task 2.1 Task 定义与配置 Task 的定义方式有如下两种: Task 的配置方式也有如下两种…...

【React 】折叠面板,点击展开时再请求数据
需求背景:使用折叠面板的形式展示数据,面板内部数据需要在打开时请求接口获取。 遇到问题:最开始使用Antd 的折叠面板组件,它对于数据直接渲染是没问题的,但是不好满足打开面板时再动态加载数据的需求,于是…...
c++学习 文件操作,模板
文件操作 #include<iostream> #include<string> #include<fstream> using namespace std; //文本操作 //程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放 //通过文件可以数据持久化 //c中对文件操作包含头文件<fstream> /…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...