Python 类对象

news2024/10/7 18:30:29

Python 类对象

经典迭代器

  • 可迭代对象的定义: 使用内置的iter可以获取迭代器的对象。如果对象实现了能返回迭代器的__iter__方法,那么对象就是可迭代的。序列都可以迭代。实现了__getitem__方法,而且接受从0开始的索引,这种对象也是可以迭代的。

  • 可迭代对象与迭代器之间的关系:Python从可迭代对象中获取迭代器。

import re
import reprlib

RE_WORD = re.compile(r'\w+')


class SentenceV2:

    def __init__(self, text):
        self.text = text
        self.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 = 0

    def __next__(self):
        try:
            word = self.words[self.index]
        except IndexError:
            raise StopIteration()
        self.index += 1
        return word

    def __iter__(self):  
        return self
  • 可迭代对象有一个__iter__方法,每次都实例化一个新迭代器。
  • 迭代器要实现__next__方法,返回单个元素,此外还要实现__iter__方法,返回迭代器本身。
  • 迭代器也是可迭代对象,但是可迭代对象不是迭代器。
生成器函数
import re
import reprlib

RE_WORD = re.compile(r'\w+')


class SentenceV3:

    def __init__(self, text):
        self.text = text
        self.words = RE_WORD.findall(text)

    def __repr__(self):
        return 'Sentence(%s)' % reprlib.repr(self.text)

    def __iter__(self):
        for word in self.words:
            # 产生当前的word
            yield word
            
            
class ArithmeticProgression:

    def __init__(self, begin, step, end=None):
        self.begin = begin
        self.step = step
        self.end = end  # None -> "infinite" series

    def __iter__(self):
        result_type = type(self.begin + self.step)
        result = result_type(self.begin)
        forever = self.end is None
        while forever or result < self.end:
            yield result
            result += self.step

只要Python函数的主体中有yield关键字,该函数就是生成器函数。调用生成器函数,返回一个生成器对象。

生成器工作原理:

  1. 生成器函数创建一个生成器对象,包装生成器函数的主体。
  2. 把生成器对象传给next()函数时,生成器函数提前执行函数主体中的下一个yield语句,返回产出的值,并在函数主体的当前位置暂停。
  3. 函数的主体返回时,Python创建的外层生成器对象抛出StopIteration异常。

上下文管理器

import sys

class LookingGlass:

    def __enter__(self):
        self.original_write = sys.stdout.write
        # 打上猴子补丁
        sys.stdout.write = self.reverse_write
        return 'JABBERWOCKY'

    def reverse_write(self, text):
        # 反转参数的内容
        self.original_write(text[::-1])

    def __exit__(self, exc_type, exc_value, traceback):
        # 将原来的方法还原
        sys.stdout.write = self.original_write
        if exc_type is ZeroDivisionError:
            print('Please DO NOT divide by zero!')
            return True

image-20240624090216546

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 = v
    def __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的本质都是调用reduce
        return functools.reduce(operator.xor, hashes, 0) 
     msg = error.format(cls_name=cls.__name__, 

attr_name=name)
raise AttributeError(msg)
# 没问题就调用父类方法
super().setattr(name, value)


### 哈希

```python
 def __hash__(self): 
        hashes = (hash(x) for x in self._components) 
        # reduce类似于递归函数,sum、any 和 all的本质都是调用reduce
        return functools.reduce(operator.xor, hashes, 0) 

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

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

相关文章

2024年,AI的机会在行业大模型吗?

前言 随着科技的不断进步&#xff0c;人工智能&#xff08;AI&#xff09;正以前所未有的速度改变着我们的世界。而在2024年&#xff0c;AI的机会无疑将更加聚焦于行业大模型。这些模型不仅代表着技术的巅峰&#xff0c;更是推动行业创新、提升效率、优化体验的关键力量。 行…

UE5 场景物体一键放入蓝图中

场景中&#xff0c;选择所有需要加入到蓝图的模型或物体。 点击 蓝图按钮&#xff0c;点击“将选项转换为蓝图” 在创建方法中&#xff0c;选择“子Actor”或着 “获取组件” 如果需要保持相对应的Actor的父子级别&#xff08;多层&#xff09;&#xff0c;那么选择“获取组件…

分布式事务msb

分布式事务使用场景 添加商品看库存够不够。库存扣减&#xff0c;扣完给订单服务一个响应&#xff0c;如果新加商品出问题了怎么回滚。 分布式事务概念 XA规范 XA规范&#xff1a;总之一句话&#xff1a; 就X/Open DTP 定义的 事务协调者与数据库之间的接口规范&#xff08;即…

2024 年计算机专业是否依旧稳坐就业市场的黄金宝座?

引言&#xff1a;选择的十字路口 随着 2024 年高考的结束&#xff0c;一股新的就业浪潮即将席卷全国 - 百万计的高三毕业生站在了人生的十字路口&#xff0c;面对着选专业这一重大决策。 计算机科学及相关领域&#xff0c;长久以来被誉为就业市场的“黄金门票”&#xff0c;吸…

代码随想录训练营第十六天 513找树左下角的值 112路径总和I 113路径总和II 106从中序和后序遍历序列构造二叉树

第一题&#xff1a; 原题链接&#xff1a;513. 找树左下角的值 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a;用回溯的思想&#xff1a; 这题就是求最大深度&#xff0c;当遍历到第一个最大深度的时候&#xff0c;记录下的节点值就是最左边的元素。 参数和返回…

声波的种类

声波可以根据不同的特性进行分类&#xff0c;主要包括频率和传播方式两个方面&#xff1a; ### 按频率分类&#xff1a; 1. **次声波**&#xff1a;频率低于20Hz的机械波&#xff0c;这类波通常不能被人耳感知。 2. **可闻声波**&#xff1a;频率在20Hz至20kHz之间的机械波&am…

5. Revit API: Application

5. Revit API: Application 前言 上一篇中&#xff0c;讲到了UI篇的Ribbon&#xff08;界面&#xff09;&#xff0c;并提到要创建 RibbonPanel&#xff0c;需要使用UIControlledApplication.CreateRibbonPanel(..)方法&#xff0c;还在结尾说到要写“UI”开头的那些个类&…

Spring循环依赖问题——从源码画流程图

文章目录 关键代码相关知识为什么要使用二级缓存为什么要使用三级缓存只使用两个缓存的问题不能解决构造器循环依赖为什么多例bean不能解决循环依赖问题初始化后代理对象赋值给原始对象解决循环依赖SpringBoot开启循环依赖 循环依赖 在线流程图 关键代码 从缓存中查询getSingl…

鸿蒙开发系统基础能力:【@ohos.hiTraceChain (分布式跟踪)】

分布式跟踪 本模块提供了端侧业务流程调用链跟踪的打点能力&#xff0c;包括业务流程跟踪的启动、结束、信息埋点等能力。 说明&#xff1a; 本模块首批接口从API version 8开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import hi…

固特超声波清洗机怎么样?三大超声波清洗机美的、固特、希亦谁更好?

眼镜是我们日常生活中不可或缺的用具&#xff0c;但随着使用时间的增长&#xff0c;眼镜上的灰尘和污垢也会逐渐积累&#xff0c;传统的清洗方法往往难以彻底清洁。为了解决这一难题&#xff0c;超声波清洗机出现了&#xff01;它利用超声波振动原理&#xff0c;可以轻松、快速…

群辉NAS中文件下载的三种方案

目录 一、迅雷套件 1、添加套件来源 2、安装套件 3、手机安装迅雷 二、qBittorrent套件 1、添加套件来源 2、改手工安装 3、更新后的问题 4、最后放弃DSM6 (1)上传文件手工安装 (2)添加套件来源 5、解决登陆报错 6、添加tracker 7、修改下载默认位置 8、手机…

【十一】【QT开发应用】模拟腾讯会议登录界面设计UI

ui 加入会议的样式表 QPushButton { /* 前景色 */ color:#0054E6; /* 背景色 */ background-color:rgb(255,255,255); /* 边框风格 */ border-style:outset; /* 边框宽度 */ border-width:0.5px; /* 边框颜色 */ border-color:gray; /* 边框倒角 */ border-radius…

python自动化测试之DDT数据驱动的实现代码

时隔已久&#xff0c;再次冒烟&#xff0c;自动化测试工作仍在继续&#xff0c;自动化测试中的数据驱动技术尤为重要&#xff0c;不然咋去实现数据分离呢&#xff0c;对吧&#xff0c;这里就简单介绍下与传统unittest自动化测试框架匹配的DDT数据驱动技术。 话不多说&#xff…

神经网络的编程基础

神经网络的编程基础 二分类 二分类是机器学习中的一种基本分类问题&#xff0c;其中每个样本被划分为两个类别中的一个&#xff0c;即正类或负类。这种分类问题在现实生活中有广泛的应用&#xff0c;例如判定邮件是否为垃圾邮件、判别某个人是否患病等。二分类模型根据样本的特…

Python高压电容导电体和水文椭圆微分

&#x1f3af;要点 &#x1f3af;二维热传导二阶偏微分方程 | &#x1f3af;调和函数和几何图曲率 | &#x1f3af;解潮汐波动方程 | &#x1f3af;解静止基态旋转球体流体运动函数 | &#x1f3af;水文空间插值 | &#x1f3af;流体流动模拟求解器 | &#x1f3af;随机算法解…

光伏半导体的种类

光照射半导体材料时&#xff0c;其电导率发生变化的实质是光生载流子的产生。在半导体中&#xff0c;价带中的电子受到一定能量的光子激发后&#xff0c;可以跃迁到导带&#xff0c;形成自由电子和空穴对&#xff0c;即光生载流子。这些光生载流子会增加半导体的导电能力&#…

NepnepxCATCTF Pwn-Chao

文章目录 参考类型混淆异常处理的栈回退机制虚表和类的恢复假想的程序结构逆向工程场景步骤解析 idabug检查找虚表strupsc_str()alloca异常逆向maindisplayupdatecreate 新东西exp和思路 参考 https://www.cnblogs.com/winmt/articles/17018284.html 类型混淆 关于C中由虚函…

【乐吾乐2D可视化组态编辑器】图表动态显示

1. 添加数据 乐吾乐2D可视化组态编辑器地址&#xff1a;https://2d.le5le.com/ 图表动态展示是指一个图表图元的数据属性&#xff08;一般是dataY&#xff09;绑定多个变量&#xff0c;建立通信后数据动态变化展示。 官网默认Echarts图表拖拽到画布中是已经添加了图元的da…

【SpringCloud-Seata源码分析3】

文章目录 事务的提交客户端提交流程服务端提交流程客户端删除undo_log 事务回滚客户端事务回滚服务端回滚事务 事务的提交 前面两篇我们分析了seata的TC初始化和TM,RM初始化&#xff0c;并且事务准备阶段源码及业务Sql执行&#xff0c;下面我们分析事务的提交源码。 客户端提…

【面试题】等保(等级保护)的工作流程

等保&#xff08;等级保护&#xff09;的工作流程主要包括以下几个步骤&#xff0c;以下将详细分点介绍&#xff1a; 系统定级&#xff1a; 确定定级对象&#xff1a;根据《信息系统等级保护管理办法》和《信息系统等级保护定级指南》的要求&#xff0c;确定需要进行等级保护的…