神技巧!在Python类初始化时进行四种暗箱操作!

Python异步类大揭秘:如何在初始化时顺利调用异步方法? 阅读详情

Python 的类中,所有以双下划线__包起来的方法,叫魔术方法,魔术方法在类或对象的某些事件发出后可以自动执行,让类具有神奇的魔力,比如常见的构造方法__new__、初始化方法__init__、析构方法__del__,今天来聊一聊__new__的妙用,主要分享以下几点:

  • __new__ 和 __init__ 的区别

  • 应用1:改变内置的不可变类型

  • 应用2:实现一个单例

  • 应用3:客户端缓存

  • 应用4:不同文件不同的解密方法

  • 应用5:Metaclasses

__new__ 和 __init__ 的区别

1、调用时机不同:new 是真正创建实例的方法,init 用于实例的初始化,new 先于 init 运行。

2、返回值不同,new 返回一个类的实例,而 init 不返回任何信息。

3、new 是 class 的方法,而 init 是对象的方法。

示例代码:

class A:
    def __new__(cls, *args, **kwargs):
        print("new", cls, args, kwargs)
        return super().__new__(cls)

    def __init__(self, *args, **kwargs):
        print("init", self, args, kwargs)


def how_object_construction_works():
    x = A(1, 2, 3, x=4)
    print(x)    
    print("===================")
    x = A.__new__(A, 1, 2, 3, x=4)
    if isinstance(x, A):
        type(x).__init__(x, 1, 2, 3, x=4)
    print(x)

if __name__ == "__main__":
    how_object_construction_works()

上述代码定义了一个类 A,在调用 A(1, 2, 3, x=4) 时先执行 new,再执行 init,等价于:

x = A.__new__(A, 1, 2, 3, x=4)
if isinstance(x, A):
    type(x).__init__(x, 1, 2, 3, x=4)

代码的运行结果如下:

new <class '__main__.A'> (1, 2, 3) {'x': 4}
init <__main__.A object at 0x7fccaec97610> (1, 2, 3) {'x': 4}
<__main__.A object at 0x7fccaec97610>
===================
new <class '__main__.A'> (1, 2, 3) {'x': 4}
init <__main__.A object at 0x7fccaec97310> (1, 2, 3) {'x': 4}
<__main__.A object at 0x7fccaec97310>

new 的主要作用就是让程序员可以自定义类的创建行为,以下是Python 的构造方法 __new__ 的常用场景:

应用1:改变内置的不可变类型

我们知道,元组是不可变类型,但是我们继承 tuple ,然后可以在 new 中,对其元组的元素进行修改,因为 new 返回之前,元组还不是元组,这在 init 函数中是无法实现的。比如说,实现一个大写的元组,代码如下:

class UppercaseTuple(tuple):
    def __new__(cls, iterable):
        upper_iterable = (s.upper() for s in iterable)
        return super().__new__(cls, upper_iterable)

    # 以下代码会报错,初始化时是无法修改的
    # def __init__(self, iterable):
    #     print(f'init {iterable}')
    #     for i, arg in enumerate(iterable):
    #         self[i] = arg.upper()

if __name__ == '__main__':
    print("UPPERCASE TUPLE EXAMPLE")
    print(UppercaseTuple(["hello", "world"]))

# UPPERCASE TUPLE EXAMPLE
# ('HELLO', 'WORLD')

应用2:实现一个单例

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls, *args, **kwargs)
        return cls._instance


if __name__ == "__main__":

    print("SINGLETON EXAMPLE")
    x = Singleton()
    y = Singleton()
    print(f"{x is y=}")
# SINGLETON EXAMPLE
# x is y=True

应用3:客户端缓存

当客户端的创建成本比较高时,比如读取文件或者数据库,可以采用以下方法,同一个客户端属于同一个实例,节省创建对象的成本,这本质就是多例模式。

class Client:
    _loaded = {}
    _db_file = "file.db"

    def __new__(cls, client_id):
        if (client := cls._loaded.get(client_id)) is not None:
            print(f"returning existing client {client_id} from cache")
            return client
        client = super().__new__(cls)
        cls._loaded[client_id] = client
        client._init_from_file(client_id, cls._db_file)
        return client

    def _init_from_file(self, client_id, file):
        # lookup client in file and read properties
        print(f"reading client {client_id} data from file, db, etc.")
        name = ...
        email = ...
        self.name = name
        self.email = email
        self.id = client_id


if __name__ == '__main__':
    print("CLIENT CACHE EXAMPLE")
    x = Client(0)
    y = Client(0)
    print(f"{x is y=}")
    z = Client(1)
# CLIENT CACHE EXAMPLE
# reading client 0 data from file, db, etc.
# returning existing client 0 from cache
# x is y=True
# reading client 1 data from file, db, etc.

应用4:不同文件不同的解密方法

先在脚本所在目录创建三个文件:plaintext_hello.txt、rot13_hello.txt、otp_hello.txt,程序会根据不同的文件选择不同的解密算法

import codecs
import itertools


class EncryptedFile:
    _registry = {}  # 'rot13' -> ROT13Text

    def __init_subclass__(cls, prefix, **kwargs):
        super().__init_subclass__(**kwargs)
        cls._registry[prefix] = cls

    def __new__(cls, path: str, key=None):
        prefix, sep, suffix = path.partition(":///")
        if sep:
            file = suffix
        else:
            file = prefix
            prefix = "file"
        subclass = cls._registry[prefix]
        obj = object.__new__(subclass)
        obj.file = file
        obj.key = key
        return obj

    def read(self) -> str:
        raise NotImplementedError


class Plaintext(EncryptedFile, prefix="file"):
    def read(self):
        with open(self.file, "r") as f:
            return f.read()


class ROT13Text(EncryptedFile, prefix="rot13"):
    def read(self):
        with open(self.file, "r") as f:
            text = f.read()
        return codecs.decode(text, "rot_13")


class OneTimePadXorText(EncryptedFile, prefix="otp"):
    def __init__(self, path, key):
        if isinstance(self.key, str):
            self.key = self.key.encode()

    def xor_bytes_with_key(self, b: bytes) -> bytes:
        return bytes(b1 ^ b2 for b1, b2 in zip(b, itertools.cycle(self.key)))

    def read(self):
        with open(self.file, "rb") as f:
            btext = f.read()
        text = self.xor_bytes_with_key(btext).decode()
        return text


if __name__ == "__main__":
    print("ENCRYPTED FILE EXAMPLE")
    print(EncryptedFile("plaintext_hello.txt").read())
    print(EncryptedFile("rot13:///rot13_hello.txt").read())
    print(EncryptedFile("otp:///otp_hello.txt", key="1234").read())
# ENCRYPTED FILE EXAMPLE
# plaintext_hello.txt
# ebg13_uryyb.gkg
# ^FCkYW_X^GL

END


 
推荐阅读:
入门: 最全的零基础学Python的问题  | 零基础学了8个月的Python  | 实战项目 |学Python就是这条捷径
干货:爬取豆瓣短评,电影《后来的我们》 | 38年NBA最佳球员分析 |   从万众期待到口碑扑街!唐探3令人失望  | 笑看新倚天屠龙记 | 灯谜答题王 |用Python做个海量小姐姐素描图 |碟中谍这么火,我用机器学习做个迷你推荐系统电影
趣味:弹球游戏  | 九宫格  | 漂亮的花 | 两百行Python《天天酷跑》游戏!
AI: 会做诗的机器人 | 给图片上色 | 预测收入 | 碟中谍这么火,我用机器学习做个迷你推荐系统电影
小工具: Pdf转Word,轻松搞定表格和水印! | 一键把html网页保存为pdf!|  再见PDF提取收费! | 用90行代码打造最强PDF转换器,word、PPT、excel、markdown、html一键转换 | 制作一款钉钉低价机票提示器! |60行代码做了一个语音壁纸切换器天天看小姐姐!|

年度爆款文案

点阅读原文,看200个Python案例!

【Python进阶】7个Python类技巧,你学会了吗? 类是面向对象编程中的基本构造块,它定义了一组具有相同属性和方法的对象。类可以看作是一个模板,用于创建具有相同特性的多个对象。Python中的类通过class关键字定义。定义一个类并创建类的实例是最基础的操作。class Dog:print(f"") # 创建类的实例 my_dog = Dog("Buddy" , 3) # 调用实例方法 my_dog . bark() # 输出: Buddy says woof! 阅读详情

相关推荐

破解雪球网acw_sc__v2加密与无限debugger反爬策略

本文详细解析了雪球网的反爬机制,重点破解了其核心的acw_sc__v2加密参数与无限debugger反调试策略。通过实战案例,从抓包分析、逆向调试到算法还原,提供了完整的Python代码实现,帮助开发者掌握应对类似加密反爬的通用方法。

weixin_29207533的博客 1897

python里的初始化使用

但是如果调用函数A需要传入参数才能运行,或者不想再去调用整个函数A获取值,此时可以将需要调用的参数初始化,变成全局参数,这样就不需要再次运行函数A,并且不仅仅只能调用得到一个return值(一个函数只能有一个return,且只能return一个变量值)比如我们在函数B想要调用函数A,可以使用调用函数A的函数名,然后得到函数A的return值。2、pytest 的Test 开头的类下边是不能包含 _模块级别的,写在模块开头。函数级别的,写在函数开头。方法级别的,也写在类开头。类级别的,写在类开头。

qq_36751833的博客 1414

别再到处找模型了!手把手教你用Xinference+Docker部署本地私有大模型(Llama2/Qwen实战)

本文详细介绍了如何使用Xinference和Docker部署本地私有化大模型(如Llama2/Qwen),涵盖硬件配置、模型管理、Docker部署及性能优化等关键步骤。通过实战案例,帮助开发者快速构建企业级AI推理服务,确保数据安全与高效运行。

weixin_28683065的博客 231

都2023年了,为什么大家还都在吹捧 Python?

近些年间,Python 的火热有目共睹,作为一种功能强大的高级编程语言,在 2018 年的时候它的流行程度就得到了大幅提高。

Python966的博客 376

electron:解决打包后报错Cannot find module ‘X‘ 运行报错各种模块缺失问题(解决electron build打包后运行应用报错启动失败或白屏,无论模块名称是什么都能解决!)

Electron app打包后启动报错:“Cannot find module 'X'”解决方案,electron-builder 打包出现 cannot find module,electron 打包后找不到module问题,electron打包运行白屏、Can not find modules ‘x‘,electron项目打包报错,electron打包后,点击生成的exe应用程序出现Cannot find module,解决electron-build打包后运行app报错:cannot find mod

✅ 精选推荐文章 4384

【YOLO目标检测全栈实战】68 模型量化:从FP32到INT8,精度不掉,速度翻倍

摘要: 模型量化能显著提升推理速度(如YOLOv5s帧率从15FPS提升至38FPS),但需避免三大误区:1)校准集需覆盖实际场景,而非随机采样;2)敏感层(如检测头)应保留FP32精度;3)预处理必须与量化前后一致。通过混合精度量化(Backbone用INT8,检测头用FP32)和逐通道量化,可实现<1%的mAP损失。关键步骤包括校准数据准备、量化感知训练及逐层精度评估,最终在Jetson Nano等边缘设备上实现速度与精度的平衡。

企鹅码农的专属播客,分享10多年的实战案例和经验解读,包含YOLO、RT-DETR、AI等各个工作领域。 145

被吹的神乎其神的Python到底都能干什么

1. 前言 最近几年 Python 被吹的神乎其神,很多同学都不清楚 Python 到底能干什么就盲目去学习 Python,今天小胖哥就 Python 的应用领域来简单盘点一下,让想学习Python 的同学找对方向不迷茫。 2. Python 的特点 这里就谈谈自己的看法,首先 Python是跨平台语言,语法很简洁,很短的代码干更多的事。另外它是脚本语言,随时随地写一段脚本就可以处理数据,十分方便。同时它也是面向对象语言,对初学者十分友好。Python 在处理各个领域的类库也十分丰富,爬虫、机器学习、

weixin_45820912的博客 936

基于YOLO26深度学习框架的文档表格识别系统的算法研究实现方法

本文研究了基于YOLO26深度学习框架的文档表格识别系统实现方法。系统采用YOLO26网络架构,通过数据预处理、模型训练、检测推理和表格分析四个模块实现高效表格识别。研究详细阐述了数据归一化、增强等技术处理,以及采用迁移学习策略优化模型训练过程。实验表明,该系统能有效识别多种表格结构并生成结构化数据,为文档自动化处理提供了可靠解决方案。

一键难忘的博客 970

Python 类的初始化

在 Python 中,类的定义中通常包含一个构造函数,它是自动调用的,以便初始化类的属性和方法。在 Python 中,类的定义通常包含一个构造函数,它用于初始化类的属性和方法。在构造函数中,可以使用 self 关键字来引用类的当前实例,并且可以访问类的属性和方法。在这个方法中,可以使用 self 关键字来引用类的当前实例,并调用其他方法或属性来初始化类的属性和方法。这是因为在 Python 中,双下划线表示一个特殊的方法,用于初始化类的属性和方法。构造函数是一个特殊的方法,用于初始化类的属性和方法。

weixin_62773441的博客 3579

手把手教你学Simulink——基于Simulink的输入输出线性化精确转矩控制

由于IOFL控制律中实时引入了当前状态的反馈(id​,iq​,ωe​),电感的变化被非线性项自动补偿,转矩仅出现微小幅度的波动(< 2%),展现出极强的参数鲁棒性。:电压方程中的耦合项(ωe​Lq​iq​和 −ωe​Ld​id​)仅通过前馈补偿,当转速 ωe​较高时,微小的前馈误差会导致显著的d-q轴电流交叉耦合;其中,ud​,uq​为定子电压,id​,iq​为定子电流,Rs​为定子电阻,Ls​为定子电感,ωe​为电角速度,ψf​为永磁体磁链,p为极对数。(步长 Ts​=10μs,即100ns?

MHD0815的博客 82

Unity 热更新技术 | (二) AssetBundle - 完整系列教程学习

开始学习热更新方面系列知识,就从这一篇开始吧! 本系列教程 会从热更新基本概念出发,详细介绍热更新相关的全套知识点。 如热更新技术基本原理、热更新主流方案、AssetBundle系列教程、Lua语言编程、Lua与Unity交互教程、Xlua框架使用、热更新实战教程等方面。 热更新作为一个开发者必备技能,如果想学习的话,可以从现在开始了哦~ 接下来从 AssetBundle - 完整系列教程学习 开始学习吧!

努力前行,总会成为自己心中的那道光 1万+

python类初始化调用自身方法_python – 调用类方法作为初始化的一部分

当前状态我有一个抽象的基类,它以numpy数组的形式托管数据,知道如何处理这些数据,哪些可以解释matplotlib如何绘制它.为了容纳不同类型的数据,它有许多子类,如下所示:class PlotData():"""Base Class"""subclasslist = []@classmethoddef register(cls):super().subclasslist.append(cls)...

weixin_35969301的博客 1921

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

神技巧,在Python类初始化时进行四种暗箱操作

Python 的类中,所有以双下划线__包起来的方法,叫魔术方法,魔术方法在类或对象的某些事件发出后可以自动执行,让类具有神奇的魔力,比如常见的构造方法__new、初始化方法init、析构方法del,今天来聊一聊new__的妙用,主要分享以下几点: new 和 init 的区别 应用1:改变内置的不可变类型 应用2:实现一个单例 应用3:客户端缓存 应用4:不同文件不同的解密方法 应用5:Metaclasses new 和 init 的区别 1、调用时机不同:new 是真正创建实例的方法,init 用于

Python_cocola的博客 224

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Python小技巧之——基类初始化

子类__init__初始化时,如果要对基类进行初始化,大家都知道可以用super:>>> class base(object): def __init__(self): print('base init') >>> class derived(base): def __init__(self): print('derived init') super(derived, se

wifeisboss的博客 4603

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

python 类初始化赋值,Python的类初始化方法

摘自Mastering Object-oriented Python隐式的基类——objectPython是面向对象程序设计语言,有一个类似root的基础类object类。任何自定义的类,都会隐式继承object。class X:passprint(X.__class__)# print(X.__class__.__base__)# 基类中的初始化方法延迟赋值这是指先创建类模板,然后在实例中定义属...

weixin_39622568的博客 2040

【Python】【技能树评测】技巧实例-说明改进和实践【02】 - 类的初始化和初始化参数

本章,继续对优快云技能树的一些例子进行了改进说明和实践。希望能帮助在技能树游泳的哥们。原来的例子,写的注解太少了,没用的基本概念解释太多,花了时间看的,反而困惑了。再加上调用了choice这个随机取值函数,搞的结果更加玄乎,这个是一个培训的文案例子,建议修正。 上述代码,创建了一个Divergence的类, 其中,定义了一个类的初始化,这里除了,self参数外,还定义了,name的参数,同时他的默认初始值为‘robot’。定义了一个类的方法,该方法从内部的列表里面,随机取一个值输出,也就是实现了猜拳的功能

山云的专栏 420

Python 类的10个技巧,让你轻松写出优雅代码

朋友,你好!在Python编程中,类(Class)是面向对象编程(OOP)的核心概念之一。掌握类的使用,不仅能让你的代码更加结构化,还能提高代码的可读性和可维护性。

公众号【伤心的辣条】资料领取~ 1121

python参数初始化_python参数初始化

python 初始化参数怎么设置class A(object): def __init__(arg): self.arg = arg 在__init__中定义python中类的初始化函数形参=0含义看来你是学c#不久的 private和public作为访问权限来 控制变量的作用域是很有必要的 这直接关系到了变量被访问的方式和范围 还有你说的那个不是等价的 虽然从赋值的效果是一样的 然而如果 你要从...

weixin_30224231的博客 3917

Python 拆分Word文档的四种实用技巧

这篇文章介绍了使用Python拆分Word文档的四种方式,包含详细的步骤介绍和代码示例。

nuclear2011的博客 3328

Python list接收返回值时无需初始化

我们知道python中list在使用时应当提前先进行初始化,否则将会报错,代码如下: class Debug: def mainProgram(self): list1 = [2, 3] for i in list1: list2.append(i) if __name__ == "__main__": main =Debug() main.mainProgram() """ name 'list2' is

u011699626的博客 649

关于牛客笔试时初始化输入(python链表初始化和列表初始化)

1.只有一个整数:a = int(input) 2.一行多个整数并用空格分开:a,b = map(int,input().split()) 3.数据较多时可用 列表存储:num = list(map(int,input().split())) 4.关于初始化链表: class Node: def __init__(self,x): self.val = x ...

sinat_35325378的博客 1137

Python 内编写类的各种技巧和方法

简介 有关 Python 内编写类的各种技巧和方法(构建和初始化、重载操作符、类描述、属性访问控制、自定义序列、反射机制、可调用对象、上下文管理、构建描述符对象、Pickling)。 你可以把它当作一个教程,进阶,或者使用参考;我希望它能够成为一份针对 Python 方法的用户友好指南。 内容目录 介绍 构建和初始化 使操作符在自定义类内工作 神奇方法——比较 神奇方法——数字 描述你的类 属性访...

Python热爱者的博客 584

在定义的时候初始化类成员:Python类设计的最佳实践

在定义的时候初始化类成员:Python类设计的最佳实践

KE17RS的博客 1068

python 基类初始化_如何初始化基类(超级类)?

How do I initialize the base (super) class?class SuperClass(object):def __init__(self, x):self.x = xclass SubClass(SuperClass):def __init__(self, y):self.y = y使用一个super对象来确保获得方法解析顺序中的下一个方法(作为绑定方法)。在Py...

weixin_28932617的博客 835
上一篇: 用Python实现股价的简单移动平均值(SMA)
下一篇: 上班可以摸鱼了!刚刚发现在VScode中可玩魂斗罗,超级玛丽!附详细攻略!
菜鸟学Python
博客等级 码龄9年 8029粉丝 571原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值