首页 > 编程语言 >Python魔法之旅-魔法方法(01)

Python魔法之旅-魔法方法(01)

时间:2024-05-28 17:02:38浏览次数:35  
标签:__ 01 Python self 魔法 value other print def

目录

一、概述

1、定义

2、作用

二、主要应用场景

1、构造和析构

2、操作符重载

3、字符串和表示

4、容器管理

5、可调用对象

6、上下文管理

7、属性访问和描述符

8、迭代器和生成器

9、数值类型

10、复制和序列化

11、自定义元类行为

12、自定义类行为

13、类型检查和转换

14、自定义异常

三、学习方法

1、理解基础

2、查阅文档

3、编写示例

4、实践应用

5、阅读他人代码

6、参加社区讨论

7、持续学习

8、练习与总结

9、注意兼容性

10、避免过度使用

四、应用示例

1、__abs__方法

1-1、语法

1-2、参数

1-3、功能

1-4、返回值

1-5、说明

1-6、用法

2、__add__方法

2-1、语法

2-2、参数

2-3、功能

2-4、返回值

2-5、说明

2-6、用法

3、__and__方法

3-1、语法

3-2、参数

3-3、功能

3-4、返回值

3-5、说明

3-6、用法

4、__bool__方法

4-1、语法

4-2、参数

4-3、功能

4-4、返回值

4-5、说明

4-6、用法 

5、__call__方法

5-1、语法

5-2、参数

5-3、功能

5-4、返回值

5-5、说明

5-6、用法 

五、推荐阅读

1、Python筑基之旅

2、Python函数之旅

3、Python算法之旅

4、博客个人主页

一、概述

1、定义

        魔法方法(Magic Methods/Special Methods,魔法方法/特殊方法/双下划线方法)是Python中一类具有特殊命名规则的方法,它们的名称通常以双下划线(`__`)开头和结尾

        魔法方法用于在特定情况下自动被Python解释器调用,而不需要显式地调用它们,它们提供了一种机制,让你可以定义自定义类时具有与内置类型相似的行为。

2、作用

        魔法方法允许开发者重载Python中的一些内置操作或函数的行为,从而为自定义的类添加特殊的功能

二、主要应用场景

1、构造和析构

1-1、__init__(self, [args...]):在创建对象时初始化属性。
1-2、__new__(cls, [args...]):在创建对象时控制实例的创建过程(通常与元类一起使用)。
1-3、__del__(self):在对象被销毁前执行清理操作,如关闭文件或释放资源。

2、操作符重载

2-1、__add__(self, other)、__sub__(self, other)、__mul__(self, other)等:自定义对象之间的算术运算。
2-2、__eq__(self, other)、__ne__(self, other)、__lt__(self, other)等:定义对象之间的比较操作。

3、字符串和表示

3-1、__str__(self):定义对象的字符串表示,常用于print()函数。
3-2、__repr__(self):定义对象的官方字符串表示,用于repr()函数和交互式解释器。

4、容器管理

4-1、__getitem__(self, key)、__setitem__(self, key, value)、__delitem__(self, key):用于实现类似列表或字典的索引访问、设置和删除操作。
4-2、__len__(self):返回对象的长度或元素个数。

5、可调用对象

5-1、__call__(self, [args...]):允许对象像函数一样被调用。

6、上下文管理

6-1、__enter__(self)、__exit__(self, exc_type, exc_val, exc_tb):用于实现上下文管理器,如with语句中的对象。

7、属性访问和描述符

7-1、__getattr__, __setattr__, __delattr__:这些方法允许对象在访问或修改不存在的属性时执行自定义操作。
7-2、描述符(Descriptors)是实现了__get__, __set__, 和__delete__方法的对象,它们可以控制对另一个对象属性的访问。

8、迭代器和生成器

8-1、__iter__和__next__:这些方法允许对象支持迭代操作,如使用for循环遍历对象。
8-2、__aiter__, __anext__:这些是异步迭代器的魔法方法,用于支持异步迭代。

9、数值类型

9-1、__int__(self)、__float__(self)、__complex__(self):定义对象到数值类型的转换。
9-2、__index__(self):定义对象用于切片时的整数转换。

10、复制和序列化

10-1、__copy__和__deepcopy__:允许对象支持浅复制和深复制操作。
10-2、__getstate__和__setstate__:用于自定义对象的序列化和反序列化过程。

11、自定义元类行为

11-1、__metaclass__(Python 2)或元类本身(Python 3):允许自定义类的创建过程,如动态创建类、修改类的定义等。

12、自定义类行为

12-1、__init__和__new__:用于初始化对象或控制对象的创建过程。
12-2、__init_subclass__:在子类被创建时调用,允许在子类中执行一些额外的操作。

13、类型检查和转换

13-1、__instancecheck__和__subclasscheck__:用于自定义isinstance()和issubclass()函数的行为。

14、自定义异常

14-1、你可以通过继承内置的Exception类来创建自定义的异常类,并定义其特定的行为。

三、学习方法

        要学好Python的魔法方法,你可以遵循以下方法及步骤:

1、理解基础

        首先确保你对Python的基本语法、数据类型、类和对象等概念有深入的理解,这些是理解魔法方法的基础。

2、查阅文档

        仔细阅读Python官方文档中关于魔法方法的部分,文档会详细解释每个魔法方法的作用、参数和返回值。你可以通过访问Python的官方网站或使用help()函数在Python解释器中查看文档。

3、编写示例

        为每个魔法方法编写简单的示例代码,以便更好地理解其用法和效果,通过实际编写和运行代码,你可以更直观地感受到魔法方法如何改变对象的行为。

4、实践应用

        在实际项目中尝试使用魔法方法。如,你可以创建一个自定义的集合类,使用__getitem__、__setitem__和__delitem__方法来实现索引操作。只有通过实践应用,你才能更深入地理解魔法方法的用途和重要性。

5、阅读他人代码

        阅读开源项目或他人编写的代码,特别是那些使用了魔法方法的代码,这可以帮助你学习如何在实际项目中使用魔法方法。通过分析他人代码中的魔法方法使用方式,你可以学习到一些新的技巧和最佳实践。

6、参加社区讨论

        参与Python社区的讨论,与其他开发者交流关于魔法方法的使用经验和技巧,在社区中提问或回答关于魔法方法的问题,这可以帮助你更深入地理解魔法方法并发现新的应用场景。

7、持续学习

        Python语言和其生态系统不断发展,新的魔法方法和功能可能会不断被引入,保持对Python社区的关注,及时学习新的魔法方法和最佳实践。

8、练习与总结

        多做练习,通过编写各种使用魔法方法的代码来巩固你的理解,定期总结你学到的知识和经验,形成自己的知识体系。

9、注意兼容性

        在使用魔法方法时,要注意不同Python版本之间的兼容性差异,确保你的代码在不同版本的Python中都能正常工作。

10、避免过度使用

        虽然魔法方法非常强大,但过度使用可能会导致代码难以理解和维护,在编写代码时,要权衡使用魔法方法的利弊,避免滥用。

        总之,学好Python的魔法方法需要不断地学习、实践和总结,只有通过不断地练习和积累经验,你才能更好地掌握这些强大的工具,并在实际项目中灵活运用它们。

四、应用示例

1、__abs__方法

1-1、语法
__abs__(self, /)
    abs(self)
1-2、参数

1-2-1、self(必须):调用该方法的对象本身。

1-2-2、/(可选):这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。

1-3、功能

        定义当使用内置的abs()函数作用于一个对象时,该对象应该如何计算其绝对值或模(magnitude)。

1-4、返回值

        返回一个非负值,表示该对象的“大小”或“绝对值”。

1-5、说明

        该方法通常用于自定义数值类型或需要支持绝对值运算的类。

1-6、用法
# 001、__abs__方法:
# 1、定义一个简单的数值类
class Number:
    def __init__(self, value):
        self.value = value
    def __abs__(self):
        return abs(self.value)
# 使用示例
num = Number(-5)
print(abs(num))  # 输出: 5,调用了__abs__方法

# 2、定义一个复数类
import math
class ComplexNumber:
    def __init__(self, real, imag):
        self.real = real
        self.imag = imag
    def __abs__(self):
        return math.sqrt(self.real ** 2 + self.imag ** 2)
# 使用示例
cnum = ComplexNumber(3, 4)
print(abs(cnum))  # 输出: 5.0(因为 3^2 + 4^2 = 25, sqrt(25) = 5)

# 3、定义一个有理数类
class RationalNumber:
    def __init__(self, numerator, denominator):
        self.numerator = numerator
        self.denominator = denominator
        self.reduce()  # 假设我们有一个reduce方法来简化分数
    def reduce(self):
        # 这里只是一个简单的示例,真实情况可能需要更复杂的逻辑来简化分数
        gcd = math.gcd(abs(self.numerator), abs(self.denominator))
        self.numerator //= gcd
        self.denominator //= gcd
    def __abs__(self):
        return RationalNumber(abs(self.numerator), self.denominator)
    def __str__(self):
        return f"{self.numerator}/{self.denominator}"
# 使用示例
rat = RationalNumber(-4, 2)
print(abs(rat))  # 输出: 2/1 或 2(取决于你如何定义 __str__ 方法)

# 4、定义一个向量类
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __abs__(self):
        return (self.x ** 2 + self.y ** 2) ** 0.5
# 使用示例
v = Vector(3, 4)
print(abs(v))  # 输出: 5.0(向量的模长或绝对值)

2、__add__方法

2-1、语法
__add__(self, other, /)
    Return self + other
2-2、参数

2-2-1、self(必须)表示调用该方法的对象本身。

2-2-2、other(必须)表示与self进行相加操作的对象。

2-2-3、/(可选)这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。

2-3、功能

        用于定义当对象使用“+”运算符进行加法运算时的行为。

2-4、返回值

        返回一个值,这个值通常表示两个对象相加的结果。

2-5、说明

        返回值可以是任何类型,但通常它应该是与原始对象类型相同或兼容的类型。

2-6、用法
# 002、__add__方法:
# 1、整数类的简单加法
class Integer:
    def __init__(self, value):
        self.value = value
    def __add__(self, other):
        if isinstance(other, Integer):
            return Integer(self.value + other.value)
        elif isinstance(other, int):
            return Integer(self.value + other)
        else:
            raise TypeError("Unsupported operand types for +: 'Integer' and '{}'".format(type(other).__name__))
    def __repr__(self):
        return "Integer({})".format(self.value)
# 使用示例
a = Integer(5)
b = Integer(3)
c = a + b  # 调用 a.__add__(b)
print(c)  # 输出: Integer(8)
d = a + 2  # 调用 a.__add__(2)
print(d)  # 输出: Integer(7)

# 2、向量类的向量加法
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __add__(self, other):
        if isinstance(other, Vector):
            return Vector(self.x + other.x, self.y + other.y)
        else:
            raise TypeError("Unsupported operand types for +: 'Vector' and '{}'".format(type(other).__name__))
    def __repr__(self):
        return "Vector({}, {})".format(self.x, self.y)
# 使用示例
v1 = Vector(1, 2)
v2 = Vector(3, 4)
v3 = v1 + v2  # 调用 v1.__add__(v2)
print(v3)  # 输出: Vector(4, 6)

3、__and__方法

3-1、语法
__and__(self, other, /)
    Return self & other
3-2、参数

3-2-1、self(必须)表示调用该方法的对象本身。

3-2-2、other(必须)表示与self进行按位与操作的对象。

3-2-3、/(可选)这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。

3-3、功能

        用于定义对象之间按位与(bitwise AND)操作的行为。

3-4、返回值

        返回一个值或另一种类型的对象,这个值表示两个操作数按位与的结果。

3-5、说明

        返回值可以是任何类型,但通常它会返回与操作数相同类型的一个新对象,或者在某些情况下返回另一种类型的对象(只要这个结果是按位与操作的逻辑结果)。

3-6、用法
# 003、__and__方法:
class BitField:
    def __init__(self, value):
        self.value = value
    def __and__(self, other):
        # 检查other是否为BitField或整数
        if isinstance(other, BitField):
            other_value = other.value
        elif isinstance(other, int):
            other_value = other
        else:
            raise TypeError(f"Unsupported operand type for &: 'BitField' and '{type(other).__name__}'")
        # 执行按位与操作并返回新的BitField对象
        return BitField(self.value & other_value)
    def __repr__(self):
        # 返回值的二进制表示(仅用于演示)
        return f"BitField(binary: {bin(self.value)[2:]}, decimal: {self.value})"
# 使用示例
bf1 = BitField(60)  # 60 in binary is 0011 1100
bf2 = BitField(13)  # 13 in binary is 0000 1101
# 执行按位与操作
result = bf1 & bf2
print(result)  # 输出: BitField(binary: 1100, decimal: 12)
# 也可以与整数进行按位与操作
result_int = bf1 & 5  # 5 in binary is 0000 0101
print(result_int)  # 输出: BitField(binary: 100, decimal: 4)

4、__bool__方法

4-1、语法
__bool__(self, /)
    True if self else False
4-2、参数

3-2-1、self(必须)表示调用该方法的对象本身。

3-2-2、/(可选)这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。

4-3、功能

        允许类的实例在需要布尔值的上下文中(如if语句、while循环的条件、bool()函数调用等)被正确地评估,即需要根据上下文做出正确的评估。

4-4、返回值

        返回一个布尔值,即TrueFalse

4-5、说明

        返回值决定了类的实例在布尔上下文中被视为True还是False

4-6、用法 
# 004、__bool__方法:
# 1、基于值的简单示例
class SimpleBool:
    def __init__(self, value):
        self.value = value
    def __bool__(self):
        return bool(self.value)
# 使用示例
s1 = SimpleBool(True)
s2 = SimpleBool(False)
s3 = SimpleBool(0)
s4 = SimpleBool(1)
print(bool(s1))  # 输出: True
print(bool(s2))  # 输出: False
print(bool(s3))  # 输出: False
print(bool(s4))  # 输出: True
if s1:
    print("s1 is True")  # 输出: s1 is True
if not s2:
    print("s2 is False")  # 输出: s2 is False

# 2、自定义条件判断
class CustomBool:
    def __init__(self, value):
        self.value = value
    def __bool__(self):
        # 假设我们想要当value大于0时返回True
        return self.value > 0
# 使用示例
c1 = CustomBool(5)
c2 = CustomBool(-3)
c3 = CustomBool(0)
print(bool(c1))  # 输出: True
print(bool(c2))  # 输出: False
print(bool(c3))  # 输出: False
if c1:
    print("c1 is greater than 0")  # 输出: c1 is greater than 0
# 3、字符串类,基于内容是否为空
class StringWithBool:
    def __init__(self, content):
        self.content = content
    def __bool__(self):
        # 如果内容非空,返回True
        return bool(self.content.strip())
# 使用示例
str1 = StringWithBool("Hello, Myelsa!")
str2 = StringWithBool("")
str3 = StringWithBool("   ")  # 只有空格
print(bool(str1))  # 输出: True
print(bool(str2))  # 输出: False
print(bool(str3))  # 输出: False(因为strip()移除了空格)  
if str1:
    print("str1 is not empty")  # 输出: str1 is not empty

5、__call__方法

5-1、语法
__call__(*args, **kwargs)
    Call self as a function
5-2、参数

5-2-1、*args(可变位置参数):允许你传递任意数量的位置参数给函数。 

5-2-2、**kwargs(可变关键字参数):允许你传递任意数量的关键字参数给函数。 

5-3、功能

        为类的实例提供函数式调用的能力。

5-4、返回值

        可以是任何类型,具体取决于你的实现,就像普通的函数一样,你可以从__call__方法中返回任何你想要的值或对象。

5-5、说明

        当实例被调用时(即使用圆括号和可能的参数),Python会自动调用该实例的__call__方法,并将括号中的参数传递给该方法。

5-6、用法 
# 005、__call__方法:
# 1、简单的函数式类
class Greeter:
    def __init__(self, name):
        self.name = name
    def __call__(self, greeting="Hello"):
        return f"{greeting}, {self.name}!"
# 使用示例
greeter = Greeter("Myelsa")
print(greeter("Hi"))  # 输出: Hi, Myelsa!
print(greeter())  # 输出: Hello, Myelsa!(因为默认参数是"Hello")
# 2、计算器类
class Calculator:
    def __init__(self, initial_value=0):
        self.value = initial_value
    def __call__(self, operand, operation="+"):
        if operation == "+":
            self.value += operand
        elif operation == "-":
            self.value -= operand
            # 可以添加更多操作,如乘法、除法等
        return self.value
# 使用示例
calc = Calculator(10)
print(calc(5))  # 输出: 15(执行加法操作)
print(calc(3, "-"))  # 输出: 12(执行减法操作)
# 3、可调用对象作为装饰器
class MyDecorator:
    def __init__(self, func):
        self.func = func
    def __call__(self, *args, **kwargs):
        print("Before function call.")
        result = self.func(*args, **kwargs)
        print("After function call.")
        return result
# 使用示例
@MyDecorator
def say_hello(name):
    print(f"Hello, {name}!")
say_hello("Jimmy")
# 输出:
# Before function call.
# Hello, Jimmy!
# After function call.
# 4、作为装饰器的类
class Timer:
    def __init__(self, func):
        self.func = func
    def __call__(self, *args, **kwargs):
        import time
        start_time = time.time()
        result = self.func(*args, **kwargs)
        end_time = time.time()
        print(f"Function {self.func.__name__} took {end_time - start_time:.6f}s to execute.")
        return result
# 使用示例
@Timer
def slow_function():
    import time
    time.sleep(1)  # 模拟耗时操作
    return "Done"
print(slow_function())  # 输出执行时间以及 "Done"
# 5、具有状态的函数式类
class Counter:
    def __init__(self, start=0):
        self.count = start
    def __call__(self):
        self.count += 1
        return self.count
# 使用示例
counter = Counter(5)
print(counter())  # 输出: 6
print(counter())  # 输出: 7
print(counter())  # 输出: 8

五、推荐阅读

1、Python筑基之旅

2、Python函数之旅

3、Python算法之旅

4、博客个人主页

标签:__,01,Python,self,魔法,value,other,print,def
From: https://blog.csdn.net/ygb_1024/article/details/139262805

相关文章

  • python+threading,实现简单的接口并发测试
    #-*-coding:utf-8-*-importthreadingfromutilsimporthttpUtilbody={"claimId":10179599,"protocols":[{"protocolUrl":None,"protocolContent":"<spanclass='c_......
  • 案例一:neo4j构建简单的知识图谱python启动
    案例一里面有4个python文件: 其中test1可以正常启动test4里面没啥内容可以不用管,其他的两个文件,会出现报错: 原因是被爬取信息的网站现在不允许任意获得了,必须要密钥,所以我们要找到这个网站去注册密钥:Tushare数据  这样就可以运行成功了;......
  • CSP历年复赛题-P1190 [NOIP2010 普及组] 接水问题
    原题链接:https://www.luogu.com.cn/problem/P1190题意解读:n个人在m个水龙头排队接水,每个人接水量不同,接完水的排队的人可以接上,求总的接水时间。解题思路:1、先把前m个人安排在m个水龙头2、对于m后面的每一个人,都排在目前m个水龙头总接水时间最短的后面3、最后看m个水龙头最大......
  • 【SCAU操作系统】实验二页面置换算法的模拟实现及命中率对比python源代码及实验报告参
    一、课程设计目的通过请求页式管理方式中页面置换算法的模拟设计,了解虚拟存储技术的特点,掌握请求页式存储管理中的页面置换算法。二、课程设计内容模拟实现OPT(最佳置换)、FIFO和LRU算法,并计算缺页率。三、要求及提示1、首先用随机数生成函数......
  • 如何使用Python和大模型进行数据分析和文本生成
    如何使用Python和大模型进行数据分析和文本生成Python语言以其简洁和强大的特性,成为了数据科学、机器学习和人工智能开发的首选语言之一。随着大模型(LargeLanguageModels,LLMs)如GPT-4的崛起,我们能够利用这些模型实现诸多复杂任务,从文本生成到智能对话、数据分析等等。在......
  • Python学习笔记-文件操作与CSV格式
    文件打开和关闭程序中的数据都存储在内存中,当程序执行完毕后,内存中的数据将丢失。文件可以用来进行数据的长期保存。open函数打开一个要做读/写操作的文件,打开文件后会返回一个文件对象,利用该文件对象可完成数据的读写操作。其常用形式为:open(filename,mode='r')#file......
  • 一款功能强大的Python工具,一键打包神器,一次编写、多平台运行!
    1、项目介绍Briefcase是一个功能强大的工具,主要用于将Python项目转化为多种平台的独立本地应用。它支持多种安装格式,使得Python项目能够轻松打包并部署到不同的操作系统和设备上,如macOS、Windows、Linux、iPhone/iPad、安卓系统以及电视操作系统等。项目地址:https://github.com......
  • CSP历年复赛题-P1179 [NOIP2010 普及组] 数字统计
    原题链接:https://www.luogu.com.cn/problem/P1179题意解读:统计l~r之间的整数包括多少个数字2。解题思路:枚举每一个数,对每一个数的每一位数字进行判断。100分代码:#include<bits/stdc++.h>usingnamespacestd;intl,r,ans;intmain(){cin>>l>>r;f......
  • python处理SQLite数据库
    1.前言数据库非常重要,程序的数据增删改查需要数据库支持。python处理数据库非常简单。而且不同类型的数据库处理逻辑方式大同小异。本文以sqlite数据库为例,介绍一下python操作数据库的方法。pythonsqlite3官方文档 注:Python操作mysqlite可以参照python&mysql基本使用2......
  • 【GPT应用】Python-GEE遥感大数据分析
    随着航空、航天、近地空间遥感平台的持续发展,遥感技术近年来取得显著进步。遥感数据的空间、时间、光谱分辨率及数据量均大幅提升,呈现出大数据特征。这为相关研究带来了新机遇,但同时也带来巨大挑战。传统的工作站和服务器已无法满足大区域、多尺度海量遥感数据处理需求。为解......