Python学习之-魔术方法

前言:

Python 中的魔术方法(Magic Methods),也称作特殊方法(Special Methods),是那些被双下划线包围的方法,例如 init。这些方法在 Python 中有特殊的含义,它们并不需要直接调用,而是在特定的情境下自动触发。通过定义或重写这些方法,可以自定义对象的行为,包括迭代、函数调用、属性访问等多种操作。

1.基本的魔术方法

在这里插入图片描述

1.1 有关属性

在这里插入图片描述

2 常见的几个魔术方法:

2.1 对象初始化:init(self[, …])

__init__我们很熟悉了,它在对象初始化的时候调用,我们一般将它理解为"构造函数"。这个方法在新建对象并进行初始化时被调用。

#!/usr/bin/env python
# coding=utf-8
"""
# @Time    : 2024/4/7 8:25
# @Author  : Summer
# @File    : test.py
# @describe:
"""


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age


person = Person('Alice', 30)
print(person.name)  # Alice

2.1.1 new 和__init__的解释

new 方法
new 是一个静态方法(虽然通常不需要显式声明为 @staticmethod),它负责创建并返回一个新的实例。也就是说,在对象的创建过程中,new 方法会被首先调用。
new 方法的第一个参数是类本身(通常命名为 cls),该方法应该返回类的一个实例。
对于不可变类型,比如整型、字符串和元组等,修改实例是不可能的,所以这些类型通常都需要通过重写 new 方法来进行实例的创建。
init 方法
init 方法用于实例的初始化操作。当 new 方法创建一个实例并返回时,这个实例随即被传递给 init 方法的 self 参数,以执行初始化。
init 不应该返回任何值,它的返回值被忽略。
调用顺序:
首先,new 方法被调用创建实例。
然后,创建出的实例(即 new 的返回值)被传递给 init 方法的 self 参数。
最后,init 方法初始化实例。

#!/usr/bin/env python
# coding=utf-8
"""
# @Time    : 2024/4/7 8:25
# @Author  : Summer
# @File    : test.py
# @describe:
"""


class MyClass(object):
    def __new__(cls, *args, **kwargs):
        print("Creating instance")
        instance = super(MyClass, cls).__new__(cls)
        return instance

    def __init__(self, value):
        print("Initializing instance")
        self.value = value


# 创建 MyClass 的一个实例
obj = MyClass("Hello")

# Creating instance
# Initializing instance

在这个例子中,当尝试创建 MyClass 的一个实例时,首先调用 new 方法来创建一个新的实例。创建成功后,这个新创建的实例会被自动传递给 init 方法以完成初始化操作。因此,你可以看到首先打印了 “Creating instance”,随后打印了 “Initializing instance”。
在大多数情况下,开发者无需重写 new 方法,只需关注 init 方法来初始化类的实例即可。但在处理不可变数据类型或者想要控制实例创建过程的高级用法时,可能需要自定义 new 方法。

2.2 字符串表现形式:str(self) 和 repr(self)

str 当你打印或者使用 str() 转换对象时被调用。
repr 用来给开发者看的字符串表现形式,它的目标是清晰无歧义。

#!/usr/bin/env python
# coding=utf-8
"""
# @Time    : 2024/4/7 8:25
# @Author  : Summer
# @File    : test.py
# @describe:
"""


class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f"Person(name={self.name}, age={self.age})"

    def __repr__(self):
        return f"Person({self.name!r}, {self.age!r})"


person = Person('Alice', 30)
print(person)  # Person(name=Alice, age=30)
print(repr(person))  # Person('Alice', 30)

2.3 属性访问:

getattr(self, name), setattr(self, name, value) 和 delattr(self, name)
这些方法负责管理属性的访问、设置和删除。

#!/usr/bin/env python
# coding=utf-8
"""
# @Time    : 2024/4/7 8:25
# @Author  : Summer
# @File    : test.py
# @describe:
"""


class Record:
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

    def __getattr__(self, name):
        return f"{name} not found"

    def __setattr__(self, name, value):
        self.__dict__[name] = value

    def __delattr__(self, name):
        del self.__dict__[name]


rec = Record(name="Alice", age=30)
print(rec.name)  # Alice
rec.location = "New York"
print(rec.location)  # New York
del rec.location
# print(rec.location) # Raises "location not found" due to __getattr__

2.4 算术运算符重载:

add(self, other), sub(self, other) 等
允许你定义对象在加减乘除等算术运算中的行为。

#!/usr/bin/env python
# coding=utf-8
"""
# @Time    : 2024/4/7 8:25
# @Author  : Summer
# @File    : test.py
# @describe:
"""


class Length:
    def __init__(self, value):
        self.value = value

    def __add__(self, other):
        return Length(self.value + other.value)


l1 = Length(5)
l2 = Length(3)
l3 = l1 + l2
print(l3.value)  # 8

2.5 容器类型方法:

len(self), getitem(self, key), setitem(self, key, value), delitem(self, key) 等
这使得对象可以表现得像容器类型一样,支持 len(), []访问等。

#!/usr/bin/env python
# coding=utf-8
"""
# @Time    : 2024/4/7 8:25
# @Author  : Summer
# @File    : test.py
# @describe:
"""


class Shelf:
    def __init__(self):
        self._items = {}

    def __setitem__(self, key, value):
        self._items[key] = value

    def __getitem__(self, key):
        return self._items.get(key, None)

    def __delitem__(self, key):
        del self._items[key]


shelf = Shelf()
shelf['book'] = 'Python Programming'
print(shelf['book'])  # Python Programming
del shelf['book']

2.6 call(self, [args…])

该方法允许类的实例跟函数一样表现,call 是 Python 中的一个特殊方法,它使得一个对象可以像函数一样被调用。当你尝试像调用函数一样调用一个对象时,如果这个对象的类中定义了 call 方法,那么这个 call 方法会被执行。

#!/usr/bin/env python
# coding=utf-8
"""
# @Time    : 2024/4/7 8:25
# @Author  : Summer
# @File    : test.py
# @describe:
"""


class Adder:
    def __init__(self, n):
        self.n = n

    def __call__(self, x):
        return self.n + x


# 创建一个 Adder 实例,它会把传入的参数增加 10
adder = Adder(10)

# 由于定义了 __call__ 方法,我们可以将 adder 当作是函数来调用
result = adder(5)  # 相当于调用 adder.__call__(5)
print(result)  # 输出 15

在这个例子中,我们定义了一个类 Adder,它有一个初始化方法和一个 call 方法。call 方法接收一个参数 x 并且返回 self.n + x。当我们创建了一个 Adder 实例 adder 并且传入了初始值 10,这个实例就可以像一个函数那样被调用。调用 adder(5) 实际上会执行 adder.call(5),最终返回值是 15。
call 方法的使用场景主要是想使得实例的行为更类似函数或者是定义可调用对象,同时保留存储状态等功能,这在使用类装饰器或者设计类似函数式编程中的函数对象时会特别有用。

2.7 format(self, [args…])

format() 函数在 Python 中用于格式化输出,它允许你控制数据的显示形式。当你用 format(your_object) 调用它时,实际上会去查找 your_object 对应类的 format 魔术方法并调用它。你可以在自己的类中定义 format 方法来自定义格式化行为。

#!/usr/bin/env python
# coding=utf-8
"""
# @Time    : 2024/4/7 8:25
# @Author  : Summer
# @File    : test.py
# @describe:
"""


class Order:
    def __init__(self, order_id, price):
        self.order_id = order_id
        self.price = price

    def __format__(self, format_spec):
        if format_spec == 'id':
            return f'Order ID: {self.order_id}'
        elif format_spec == 'price':
            return f'Order Price: ${self.price:.2f}'
        else:
            return f'Order ID: {self.order_id}, Price: ${self.price:.2f}'


# 创建一个 Order 对象
order = Order('123', 99.99)

# 使用 format() 进行格式化
formatted_order_id = format(order, 'id')
formatted_order_price = format(order, 'price')
formatted_order_default = format(order)  # 没有指定 format_spec,或者 format_spec 为空字符串

print(formatted_order_id)  # 输出 Order ID: 123
print(formatted_order_price)  # 输出 Order Price: $99.99
print(formatted_order_default)  # 输出 Order ID: 123, Price: $99.99

在这个例子中,我们定义了一个 Order 类,它有一个 format 方法,该方法接收一个参数 format_spec,它是一个字符串,指示如何格式化该对象。根据 format_spec 的值,format 返回不同的字符串。如果 format_spec 是 ‘id’,则只输出订单 ID;如果是 ‘price’,则只输出价格;如果 format_spec 不是这两种情况,它就会输出订单 ID 和价格。
这样,无论是直接调用 Python 内置的 format() 函数还是在字符串格式化时使用冒号 : 后跟格式说明符 {my_object:format_spec},都会使用对象的 format 方法进行格式化。

总结

对象的创建和销毁:
控制对象的创建 (new)、初始化 (init) 和销毁 (del) 的过程。
对象表示:
定制对象的字符串表示,包括通过 str 提供给用户的可打印版本,以及通过 repr 提供给开发者的官方字符串表示。
属性访问管理:
管理和自定义对象属性的访问、设置和删除 (getattr, setattr, delattr 等)。包括支持点号(.)运算符进行属性访问和动态属性。
容器类型模拟:
使自定义对象的行为类似于内置的容器类型,如序列和映射(getitem, setitem, delitem, len 等)。
算术和比较操作符重载:
定义对象如何相互作用,并对算术运算 (add, mul, 等) 和比较运算 (lt, eq, 等) 进行重载。
可调用对象:
通过 call 方法,将实例变为可调用,即像函数那样可以执行。
上下文管理器:
使对象可以用在 with 语句中,提供资源管理功能,如文件打开和关闭(enter, exit)。
迭代器和生成器:
让对象支持迭代,包括定义迭代器行为 (iter, next) 和生成器行为。
与 Python 内建类型及运动环境的集成:
包括定义对象的哈希 (hash),布尔值转换 (bool),大小 (len),以及格式化 (format) 等。
通过定义这些魔术方法,Python允许开发者以非常灵活和直观的方式来控制对象的行为。这一机制是Python的核心特性之一,为语言提供了极大的表达力和一致性。其实魔法方法远远不止这些,还有很多很多也值得我们去使用,Python中的魔法方法就跟它的名字一样有魔法,总是可以便捷的给你提供你所需要的各种需求,它们是Python面向对象编程的一大利器,使用魔术方法能构造出非常优美的代码结构。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(免费分享)基于springboot,vue问卷调查系统

用户注册、用户登录、创建调查问卷、编辑问卷问题和选型(支持题型:单选、多选、单行文本、多行文本、数字、评分、日期、文本描述)、保存和发布问卷、停止问卷调查、游客填写调查问卷(一个IP地址只能填写一次) 技术&a…

Adobe After Effects 2024 v24.3 (macOS, Windows) - 后期特效

Adobe After Effects 2024 v24.3 (macOS, Windows) - 后期特效 Acrobat、After Effects、Animate、Audition、Bridge、Character Animator、Dimension、Dreamweaver、Illustrator、InCopy、InDesign、Lightroom Classic、Media Encoder、Photoshop、Premiere Pro、Adobe XD 请…

支持编写任何类型的爬虫:基于 Golang 的优雅爬虫框架 | 开源日报 No.216

gocolly/colly Stars: 21.5k License: Apache-2.0 colly 是 Golang 的优雅爬虫和爬虫框架。 该项目提供了一个清晰的接口,用于编写任何类型的爬虫/抓取器/蜘蛛。Colly 可以轻松从网站中提取结构化数据,可用于数据挖掘、数据处理或存档等各种应用。 其主…

如何把学浪app的视频保存本地

如何把学浪app里面的视频保存到本地,其实很简单,只需要用到一个工具,那就是小浪助手.exe 这里我已经把小浪助手.exe打包好了,有需要得话自己下载 链接:https://pan.baidu.com/s/1y7vcqILToULrYApxfEzj_Q?pwdkqvj 提…

在线视频教育平台|基于Springboot的在线视频教育平台系统设计与实现(源码+数据库+文档)

在线视频教育平台目录 基于Springboot的在线视频教育平台系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1、前台: 2、后台 用户功能模块 教师功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&a…

如何在Python中将HTML实体代码转换为文本

在处理HTML数据时&#xff0c;有时会遇到HTML实体代码&#xff0c;这些代码是为了在HTML中表示特殊字符而使用的。例如&#xff0c;<表示小于符号(<)&#xff0c;>表示大于符号(>)&#xff0c;&表示和符号(&)等等。那么当我们在实际操作中可能会遇到下面的…

Centos7使用docker安装Jenkins(含pipeline脚本语句)

一、下载Jenkins docker pull jenkins/jenkins:lts 二、启动Jenkins docker run \-u root \--rm \-d \-p 8081:8080 \-p 50000:50000 \-v /root/docker/jenkins/var/jenkins_home:/var/jenkins_home \-v /var/run/docker.sock:/var/run/docker.sock \-v /usr/bin/docker:/usr…

初学者也能轻松使用的原型设计工具

原型是之前所有 UX 设计工作的合并&#xff0c;是一种单一、可视、功能的产品&#xff0c;用于验证假设和测试设计。作为产品经理或设计师&#xff0c;原型设计工具是必不可少的合作伙伴。目前网站原型设计中可以使用的工具有很多&#xff0c;比如 Axure、Sketch、XD、Figma 等…

Vue2 —— 学习(一)

目录 一、了解 Vue &#xff08;一&#xff09;介绍 &#xff08;二&#xff09;Vue 特点 &#xff08;三&#xff09;Vue 网站 1.学习&#xff1a; 2.生态系统&#xff1a; 3.团队 二、搭建 Vue 开发环境 &#xff08;一&#xff09;安装与引入 Vue 1.直接引入 2.N…

微信小程序认证,备案,域名,证书,上线全流程

1.微信公众平台完成小程序认证和备案。 配置服务类目&#xff1a; 2.购买域名并完成域名实名认证和备案&#xff0c;公安备案。 3.购买https证书。 下载证书&#xff1a; 4.创建目录 mkdir -p /home/app/exam/ssl。上传证书到该目录下。 5.创建nginx配置文件: vim /usr/local…

09 Python进阶: JSON 数据解析、日期和时间

JSON 数据解析 JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式。 Python3 中可以使用 json 模块来对 JSON 数据进行编解码&#xff0c;它包含了两个函数&#xff1a; json.dumps(): 对数据进行编码。 json.loads(): 对数据进行解码。 Python 编码为 JSON …

Hugging Face入门(一)

简介 本文主要内容&#xff1a; Hugging Face介绍环境搭建敲两个例子 Hugging Face介绍 Hugging Face 是一家法美合资公司&#xff0c;总部位于纽约市&#xff0c;成立于2016年。它由法国企业家Clment Delangue、Julien Chaumond和Thomas Wolf在纽约市创立&#xff0c;最初是…

精品丨PowerBI负载测试和容量规划

当选择Power BI作为业务报表平台时&#xff0c;如何判断许可证的选择是否符合业务需求&#xff0c;价格占了主导因素。 Power BI的定价是基于SKU和服务器内核决定的&#xff0c;但是很多IT的负责人都不确定自己公司业务具体需要多少。 不幸的是&#xff0c;Power BI的容量和预期…

HiveSQL如何生成连续日期剖析

HiveSQL如何生成连续日期剖析 情景假设&#xff1a; 有一结果表&#xff0c;表中有start_dt和end_dt两个字段&#xff0c;&#xff0c;想要根据开始和结束时间生成连续日期的多条数据&#xff0c;应该怎么做&#xff1f;直接上结果sql。&#xff08;为了便于演示和测试这里通过…

golang slice总结

目录 概述 一、什么是slice 二、slice的声明 三、slice的初始化、创建 make方式创建 创建一个包含指定长度的切片 创建一个指定长度和容量的切片 创建一个空切片 创建一个长度和容量都为 0 的切片 new方式创建 短声明初始化切片 通过一个数组来创建切片 声明一个 …

C++可变参数模板

可变参数模板 一个可变参数模板就是一个接受可变数目参数的模板函数或模板类。 可变数目的参数被称为参数包。 存在两种参数包&#xff1a; 模板参数类&#xff0c;表示零个或多个模板参数&#xff1b;函数参数包&#xff0c;表示零个或多个函数参数。 我们用一个省略号来…

雷弗流体创新技术装备与您与您相约2024第13届生物发酵展

参展企业介绍 保定雷弗流体科技有限公司于2010年1月成立。为创新型企业&#xff0c;荣获国家级高新技术企业、国家级专精特新小巨人企业、河北省单项冠军企业、组织部巨人计划创业团队等荣誉称号。 保定雷弗流体科技有限公司现有职工180人&#xff0c;其中工程技术人员53人。现…

GitHub入门与实践

ISBN: 978-7-115-39409-5 作者&#xff1a;【日】大塚弘记 译者&#xff1a;支鹏浩、刘斌 页数&#xff1a;255页 阅读时间&#xff1a;2023-08-05 推荐指数&#xff1a;★★★★★ 好久之前读完的了&#xff0c;一直没有写笔记。 这本入门Git的书籍还是非常推荐的&#xff0c;…

【服务器部署篇】Linux下安装Docker容器

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过大学刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0…

X服务器远程连接问题解决:Bad displayname ““‘或Missing X server or $DISPLAY

X服务器远程连接问题 报错1 ImportError: this platform is not supported: (failed to acquire X connection: Bad displayname "", DisplayNameError()) Try one of the following resolutions: * Please make surethat you have an X server running, and that …