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

目录

一、概述

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、避免过度使用

四、魔法方法

17、__float__方法

17-1、语法

17-2、参数

17-3、功能

17-4、返回值

17-5、说明

17-6、用法

18、__floor__方法

18-1、语法

18-2、参数

18-3、功能

18-4、返回值

18-5、说明

18-6、用法

19、__floordiv__方法

19-1、语法

19-2、参数

19-3、功能

19-4、返回值

19-5、说明

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

四、魔法方法

17、__float__方法

17-1、语法
__float__(self, /)float(self)
17-2、参数

17-2-1、self(必须)一个对实例对象本身的引用,在类的所有方法中都会自动传递。

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

17-3、功能

        用于定义一个对象到浮点数的转换规则。

17-4、返回值

        返回一个浮点数。

17-5、说明

        具体来说,以下几种情况可能会触发__float__方法的调用:

17-5-1、使用内置的float函数尝试将一个对象转换为浮点数时。

17-5-2、在需要进行数学运算(如加法、减法、乘法、除法等)的上下文中,如果操作数之一是对

象,而另一个是浮点数或需要浮点数的操作(如除法),则可能会调用该对象的__float__方法。

17-5-3、在需要浮点数类型的其他内置函数或方法中,如果提供了不支持直接操作的对象,可能会

调用该对象的__float__方法。

17-6、用法
# 017、__float__方法:
# 1、简单的数值类
# 定义一个名为SimpleNumber的类
class SimpleNumber:# 类的初始化方法,当创建SimpleNumber对象时自动调用def __init__(self, value):# 将传入的value参数赋值给对象的value属性self.value = value# 定义__float__方法,用于将对象转换为浮点数def __float__(self):# 返回self.value的浮点数形式return float(self.value)
# 如果这个脚本作为主程序运行(而不是被导入为模块)
if __name__ == '__main__':# 创建一个SimpleNumber对象n,并传入值5.2n = SimpleNumber(5.2)# 使用内置的float函数和SimpleNumber类的__float__方法将n转换为浮点数f = float(n)# 打印转换后的浮点数fprint(f)  # 输出: 5.2# 2、分数类(有理数)
# 定义一个名为Fraction的类,用于表示分数
class Fraction:# 初始化方法,当创建Fraction对象时调用def __init__(self, numerator, denominator):# 设置分数的分子self.numerator = numerator# 设置分数的分母self.denominator = denominator# 定义转换为浮点数的特殊方法def __float__(self):# 返回分数的浮点数值(即分子除以分母)return self.numerator / self.denominator
# 如果这个脚本作为主程序运行(而不是被导入为模块)
if __name__ == '__main__':# 创建一个Fraction对象f,分子为3,分母为4f = Fraction(3, 4)# 使用内置的float函数和Fraction类的__float__方法将f转换为浮点数float_f = float(f)# 打印转换后的浮点数float_fprint(float_f)  # 输出: 0.75# 3、带有单位的度量类(如距离)
# 定义一个名为Distance的类,用于表示距离
class Distance:# 初始化方法,用于创建Distance对象时设置距离(以米为单位)def __init__(self, meters):# 将传入的距离值(以米为单位)赋值给对象的meters属性self.meters = meters# 定义转换为浮点数的特殊方法# 当尝试将Distance对象转换为浮点数时,会调用这个方法def __float__(self):# 返回Distance对象的meters属性的值,作为浮点数return self.meters
# 如果这个脚本作为主程序运行(而不是被导入为模块)
if __name__ == '__main__':# 创建一个Distance对象d,表示100.5米的距离d = Distance(100.5)# 使用内置的float函数和Distance类的__float__方法将d转换为浮点数float_d = float(d)# 打印转换后的浮点数float_dprint(float_d)  # 输出: 100.5# 4、复数类(尽管Python内置了复数类型,但可以作为示例)
# 定义一个名为MyComplex的类,用于表示复数
class MyComplex:# 初始化方法,用于创建MyComplex对象时设置实部和虚部def __init__(self, real, imag):# 设置实部self.real = real# 设置虚部self.imag = imag# 定义转换为浮点数的特殊方法# 当尝试将MyComplex对象转换为浮点数时,会调用此方法def __float__(self):# 如果虚部不为0if self.imag != 0:# 抛出ValueError异常,表示不能将有虚部的复数转换为浮点数raise ValueError("Cannot convert complex number with imaginary part to float")# 如果虚部为0,则返回实部的浮点数值return float(self.real)
# 如果这个脚本作为主程序运行(而不是被导入为模块)
if __name__ == '__main__':# 创建一个实部为3,虚部为0的MyComplex对象cc = MyComplex(3, 0)# 使用内置的float函数和MyComplex类的__float__方法将c转换为浮点数f = float(c)# 打印转换后的浮点数fprint(f)  # 输出: 3.0try:# 创建一个实部为3,虚部为4的MyComplex对象c_with_imagc_with_imag = MyComplex(3, 4)# 尝试将c_with_imag转换为浮点数,但由于虚部不为0,所以会抛出ValueError异常float_c_with_imag = float(c_with_imag)  # 这会抛出ValueErrorexcept ValueError as e:# 捕获ValueError异常并打印异常信息print(e)  # 输出: Cannot convert complex number with imaginary part to float# 5、时间类(转换为以秒为单位的浮点数)
# 从datetime模块中导入timedelta类,timedelta类用于表示两个日期或时间之间的差异
from datetime import timedelta
# 定义一个名为TimeDuration的类,用于封装timedelta并允许通过不同的时间单位进行初始化
class TimeDuration:def __init__(self, days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0):# 因为timedelta不接受milliseconds参数,并且weeks参数需要转换为days,所以我们先进行计算# 将weeks转换为days(1周 = 7天)# 注意:在Python 3中,timedelta直接支持weeks参数,但在Python 2中不支持td = timedelta(days=days + weeks * 7, seconds=seconds, microseconds=microseconds, minutes=minutes, hours=hours)# 如果提供了毫秒(milliseconds),则需要将其转换为秒和微秒# 注意:这里我们省略了毫秒的转换,因为timedelta不接受毫秒作为直接参数# 如果需要,可以在此添加转换逻辑# 将计算好的timedelta赋值给实例的duration属性self.duration = td# 定义转换为浮点数的特殊方法,返回时间差的总秒数def __float__(self):# 调用辅助函数total_seconds来获取duration的总秒数# 注意:在Python 3中,timedelta有一个total_seconds()方法,但在Python 2中没有return total_seconds(self.duration)
# 辅助函数,用于计算timedelta对象的总秒数
# 在Python 2中,timedelta没有直接的total_seconds方法,所以我们自己实现
def total_seconds(td):# 计算总秒数,包括天、小时、分钟、秒和微秒return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 1e6) / 1e6
if __name__ == '__main__':# 创建一个TimeDuration对象,表示1天2小时30分钟的时间差td = TimeDuration(days=1, hours=2, minutes=30)# 使用内置的float函数和TimeDuration类的__float__方法将td转换为浮点数(总秒数)float_td = float(td)# 打印转换后的总秒数print(float_td)  # 输出: 95400.0(具体取决于你的系统时间精度,但在这个例子中应该是准确的)# 6、字符串表示的数字转换为浮点数
# 定义一个名为 StringNumber 的类,用于将字符串表示的数字转换为浮点数
class StringNumber:# 初始化方法,接收一个字符串类型的数字作为参数def __init__(self, number_str):# 将接收到的字符串类型的数字保存到实例变量 number_str 中self.number_str = number_str# 定义转换为浮点数的特殊方法# 当尝试将 StringNumber 对象转换为浮点数时,会调用此方法def __float__(self):# 使用 Python 内置的 float 函数将 number_str 转换为浮点数# 并返回这个浮点数return float(self.number_str)
# 判断当前脚本是否作为主程序运行(而不是被导入为模块)
if __name__ == '__main__':# 创建一个 StringNumber 对象,传入一个表示数字的字符串 "3.14159"sn = StringNumber("3.14159")# 使用内置的 float 函数和 StringNumber 类的 __float__ 方法将 sn 转换为浮点数# 注意:这里实际上不需要显式调用 float(sn),因为当 sn 被用于需要浮点数的上下文中时,# Python 会自动调用 sn 的 __float__ 方法。但为了展示和明确转换,这里显式调用了 float(sn)f = float(sn)# 打印转换后的浮点数print(f)  # 输出: 3.14159

18、__floor__方法

18-1、语法
__floor__(self, /)Flooring an Integral returns itself
18-2、参数

18-2-1、self(必须)一个对实例对象本身的引用,在类的所有方法中都会自动传递。

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

18-3、功能

        用于定义数值类型的“向下取整”行为。

18-4、返回值

        返回不大于对象所表示数值的最大整数,也就是所谓的“向下取整”或“地板除”的结果。

18-5、说明

        关于返回值,__floor__方法应该返回一个与原始对象相同类型或兼容类型的对象,其值是不大于原始对象所表示数值的最大整数。

18-6、用法
# 018、__floor__方法:
# 1、基本使用
# 定义一个名为 MyNumber 的类,用于封装一个数值并提供一些特殊方法
class MyNumber:# 类的初始化方法,用于创建 MyNumber 类的实例def __init__(self, value):# 将传入的 value 参数赋值给实例变量 self.valueself.value = value# 定义一个特殊方法 __floor__,用于返回 self.value 的向下取整值def __floor__(self):# 导入 math 模块,尽管在类中导入模块不是最佳实践,但这里为了注释而保留import math# 调用 math.floor 方法对 self.value 进行向下取整,并返回结果return math.floor(self.value)
# 当这个脚本作为主程序运行时,以下代码块会被执行
if __name__ == '__main__':# 创建一个 MyNumber 类的实例 num,并传入初始值 3.7num = MyNumber(3.7)# 调用 num 实例的 __floor__ 方法,并打印返回的结果,即 3.7 的向下取整值print(num.__floor__())  # 输出: 3# 2、自定义运算符中的使用
# 导入math模块,该模块包含了一些数学运算的函数和常量
import math
# 定义一个名为MyNumber的类,用于封装数值并提供自定义的数学运算
class MyNumber:# 初始化方法,用于创建MyNumber对象时设置初始值def __init__(self, value):self.value = value  # 将传入的value赋值给对象的value属性# 定义一个特殊方法__floor__,用于返回对象的value属性的向下取整值def __floor__(self):return math.floor(self.value)  # 使用math模块中的floor函数对value进行向下取整# 定义一个特殊方法__int__,用于将MyNumber对象转换为整数def __int__(self):return int(self.value)  # 定义__int__方法以返回整数值,这里将value转换为整数并返回# 定义一个特殊方法__add__,用于实现MyNumber对象之间的加法运算def __add__(self, other):if isinstance(other, MyNumber):  # 如果other也是MyNumber对象return MyNumber(self.value + other.value)  # 返回两个对象value属性之和组成的新MyNumber对象else:  # 如果other不是MyNumber对象return MyNumber(self.value + other)  # 返回对象value属性与other之和组成的新MyNumber对象# 定义一个特殊方法__floordiv__,用于实现MyNumber对象之间的整数除法运算def __floordiv__(self, other):if isinstance(other, MyNumber):  # 如果other也是MyNumber对象floored_self = self.__floor__()  # 对self的value属性进行向下取整floored_other = other.__floor__()  # 对other的value属性进行向下取整return MyNumber(floored_self // floored_other)  # 返回两个向下取整后的值进行整除运算的结果组成的新MyNumber对象else:  # 如果other不是MyNumber对象return MyNumber(self.__floor__() // other)  # 对self的value属性进行向下取整,然后与other进行整除运算,返回结果组成的新MyNumber对象
# 当这个脚本作为主程序运行时,以下代码块会被执行
if __name__ == '__main__':# 创建两个MyNumber对象num1和num2,并分别设置初始值7.3和2num1 = MyNumber(7.3)num2 = MyNumber(2)# 使用//运算符调用num1的__floordiv__方法,与num2进行整数除法运算,并打印结果print(num1 // num2)  # 使用__floordiv__,输出: MyNumber(3)# 将num1和num2进行整数除法运算的结果转换为整数并打印print(int(num1 // num2))  # 现在可以正确转换为整数,输出: 3# 3、在类中自动转换
# 定义一个名为MyNumber的类,用于封装数值并提供一些特殊方法
class MyNumber:# 类的初始化方法,用于设置对象的初始值def __init__(self, value):# 将传入的value参数赋值给对象的value属性self.value = value# 定义一个特殊方法__floor__,用于返回对象value属性的向下取整值def __floor__(self):# 导入math模块,该模块包含数学相关的函数import math# 调用math模块中的floor函数对value进行向下取整,并返回结果return math.floor(self.value)# 定义一个特殊方法__int__,用于将对象转换为整数类型def __int__(self):# 调用__floor__方法获取value的向下取整值# 然后将该值转换为整数类型并返回return int(self.__floor__())
# 当这个脚本作为主程序运行时,以下代码块会被执行
if __name__ == '__main__':# 创建一个MyNumber对象num,并传入初始值3.7num = MyNumber(3.7)# 调用num对象的__int__方法,将其转换为整数类型并打印结果# 这里通过内置的int函数间接调用了num的__int__方法print(int(num))  # 输出: 3# 4、类的继承与重写
# 定义一个名为MyNumber的类,用于封装数值并提供向下取整的方法
class MyNumber:# 类的初始化方法,用于设置对象的初始值def __init__(self, value):# 将传入的value参数赋值给对象的value属性self.value = value# 定义一个特殊方法__floor__,用于返回对象value属性的向下取整值def __floor__(self):# 导入math模块(虽然通常建议在文件顶部导入,但这里为了说明也可在方法内部导入)import math# 调用math模块中的floor函数对value进行向下取整,并返回结果return math.floor(self.value)# 定义一个特殊方法__int__,用于将对象转换为整数类型def __int__(self):# 调用__floor__方法获取value的向下取整值# 然后将该值转换为整数类型并返回return int(self.__floor__())
# 定义一个继承自MyNumber的SpecialNumber类
class SpecialNumber(MyNumber):# 重写父类MyNumber的__floor__方法def __floor__(self):# 使用super()函数调用父类MyNumber的__floor__方法# 然后将返回的结果减1,得到SpecialNumber对象的特殊向下取整值return super().__floor__() - 1
# 当这个脚本作为主程序运行时,以下代码块会被执行
if __name__ == '__main__':# 创建一个SpecialNumber对象num,并传入初始值4.3num = SpecialNumber(4.3)# 调用num对象的__int__方法,将其转换为整数类型并打印结果# 这里通过内置的int函数间接调用了num的__int__方法# SpecialNumber类重写了__floor__方法,所以其__int__方法返回的是特殊向下取整后的整数值print(int(num))  # 输出: 3,因为 4.3 向下取整是 4,然后减 1 得到 3# 5、与其他类型进行比较
# 定义一个名为MyNumber的类,用于封装数值并提供一些特殊方法
class MyNumber:# 类的初始化方法,用于设置对象的初始值def __init__(self, value):# 将传入的value参数赋值给对象的value属性self.value = value# 定义一个特殊方法__floor__,用于返回对象value属性的向下取整值def __floor__(self):# 导入math模块(尽管通常在文件顶部导入模块,但在此为了注释说明也可以放在方法内部)import math# 调用math模块中的floor函数对value进行向下取整,并返回结果return math.floor(self.value)# 定义一个特殊方法__eq__,用于比较两个对象是否相等def __eq__(self, other):# 如果other是整数类型if isinstance(other, int):# 则比较MyNumber对象的向下取整值是否等于otherreturn self.__floor__() == other# 如果other不是整数类型,则返回NotImplemented,表示不支持该类型的比较# 这样可以让Python尝试进行其他类型的比较(如other也是MyNumber对象)return NotImplemented
# 当这个脚本作为主程序运行时,以下代码块会被执行
if __name__ == '__main__':# 创建一个MyNumber对象num,并传入初始值3.0num = MyNumber(3.0)# 使用==操作符比较num对象和整数3是否相等# 由于num的value是3.0,向下取整后仍为3,所以比较结果为Trueprint(num == 3)  # 输出: True# 6: 自定义格式化输出
# 定义一个名为 MyNumber 的类
class MyNumber:# 类的初始化方法,用于创建 MyNumber 类的实例def __init__(self, value):# 将传入的 value 赋值给实例变量 self.valueself.value = value# 定义一个特殊方法 __floor__,它用于实现取整(向下取整)的功能def __floor__(self):# 导入 math 模块(尽管这里最好是在文件顶部导入,但为了符合仅注释代码的要求,这里也可以接受)import math# 使用 math.floor 方法对 self.value 进行向下取整,并返回结果return math.floor(self.value)# 定义一个特殊方法 __format__,它允许对象自定义其字符串表示形式# format_spec 是格式说明符,它描述了如何格式化对象def __format__(self, format_spec):# 如果格式说明符为 '.floor',则调用 __floor__ 方法并返回其结果的字符串形式if format_spec == '.floor':return str(self.__floor__())# 如果格式说明符不是 '.floor',则返回 NotImplemented,表示不支持该格式return NotImplemented
# 如果当前运行的脚本(而不是导入的模块)是主程序,则执行以下代码
if __name__ == '__main__':# 创建一个 MyNumber 类的实例 num,并传入值 3.7num = MyNumber(3.7)# 使用 format 函数和 '.floor' 格式说明符来格式化 num 对象,并打印结果# 由于 MyNumber 类定义了 __format__ 方法并处理了 '.floor' 格式说明符,因此这里会输出 '3'print(format(num, '.floor'))  # 输出: '3'

19、__floordiv__方法

19-1、语法
__floordiv__(self, other, /)Return self//other
19-2、参数

19-2-1、self(必须)一个对实例对象本身的引用,在类的所有方法中都会自动传递。

19-2-2、other(必须)表示与self进行地板除法的另一个值,它可以是任何类型,但通常应该是与

self兼容的数值类型。

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

19-3、功能

        用于定义当对象使用//运算符进行地板除法时的行为。

19-4、返回值

        返回一个表示地板除法结果的对象。

19-5、说明

        对于__floordiv__方法,它的返回值通常是与原始对象类型相同或兼容的数值类型对象,其值是两个操作数进行地板除法的结果,然而,这个返回值的具体类型完全取决于你的实现。

19-6、用法
# 019、__floordiv__方法:
# 1、简单的整数类
class SimpleInt:def __init__(self, value):# 初始化方法,设置实例的 value 属性self.value = valuedef __floordiv__(self, other):# 定义地板除法运算符的行为if isinstance(other, (int, float)):# 如果 other 是整数或浮点数,则执行地板除法并返回结果return self.value // otherelse:# 如果 other 不是整数或浮点数,则抛出类型错误raise TypeError("Unsupported operand type(s) for //: 'SimpleInt' and '{}'".format(type(other).__name__))
if __name__ == '__main__':# 创建一个 SimpleInt 类的实例 a,并设置其值为 10a = SimpleInt(10)# 定义一个普通的整数 b,其值为 3b = 3# 使用 // 运算符调用 a 的 __floordiv__ 方法,并打印结果# 这里将输出整数 3,因为 10 // 3 的结果是 3print(a // b)  # 这会调用 SimpleInt 的 __floordiv__ 方法,输出应为 3# 2、自定义除法规则类
class CustomDiv:def __init__(self, value):# 初始化方法,设置实例的value属性self.value = valuedef __floordiv__(self, other):# 地板除法特殊方法,用于处理自定义除法规则if isinstance(other, int):# 检查other是否为整数# 如果self.value是非负数,则执行正常的地板除法(即减去余数)# 如果self.value是负数,则先取负数的绝对值进行整除,再取负值(因为负数的整除行为是向负无穷方向取整)return self.value - (self.value % other) if self.value >= 0 else -((-self.value) // other)else:# 如果other不是整数,则抛出类型错误raise TypeError("Unsupported operand type(s) for //: 'CustomDiv' and '{}'".format(type(other).__name__))
if __name__ == '__main__':# 创建一个CustomDiv实例,并设置其value为10cd = CustomDiv(10)# 调用CustomDiv的__floordiv__方法(即执行cd // 3),并打印结果# 因为10 >= 0,所以直接执行self.value - (self.value % other),即10 - (10 % 3) = 10 - 1 = 9print(cd // 3)  # 输出:9# 直接使用类名和参数创建另一个CustomDiv实例,其value为-10# 调用该实例的__floordiv__方法(即执行CustomDiv(-10) // 3),并打印结果# 因为-10 < 0,所以先取-10的绝对值(即10),执行整除10 // 3 = 3,然后取负值,即-3print(CustomDiv(-10) // 3)  # 输出:-3(因为-10 < 0, 所以取-((-10) // 3))# 3、时间类(用于计算时间差)
from datetime import timedelta
class TimeDuration:def __init__(self, hours, minutes, seconds):# 初始化方法,接收小时、分钟和秒作为参数,并使用timedelta创建时间差对象self.duration = timedelta(hours=hours, minutes=minutes, seconds=seconds)def __floordiv__(self, other):# 定义地板除法运算符的行为if isinstance(other, TimeDuration):# 如果 other 是 TimeDuration 的实例,则计算 self 的总秒数与 other 的总秒数# 使用整数除法来计算 self 可以包含多少个 other# 假设我们想以 other 的时长为单位,计算 self 的时长可以包含多少个 othertotal_seconds = self.duration.total_seconds()  # 获取 self 的总秒数other_seconds = other.duration.total_seconds()  # 获取 other 的总秒数# 使用整数除法 // 来获取结果,并返回结果return int(total_seconds // other_seconds)else:# 如果 other 不是 TimeDuration 的实例,则抛出类型错误raise TypeError(f"Unsupported operand type(s) for //: 'TimeDuration' and '{type(other).__name__}'")def __str__(self):# 定义字符串表示方法,返回 timedelta 对象的字符串表示return str(self.duration)
if __name__ == '__main__':# 创建一个 TimeDuration 对象 duration_a,表示 2 小时 30 分钟duration_a = TimeDuration(2, 30, 0)  # 2小时30分钟# 创建一个 TimeDuration 对象 duration_b,表示 15 分钟duration_b = TimeDuration(0, 15, 0)  # 15分钟# 使用地板除法运算符 // 来计算 duration_a 包含多少个 duration_b# 输出结果应为 10,因为 2 小时 30 分钟 包含 10 个 15 分钟print(duration_a // duration_b)  # 输出: 10 (因为 2小时30分钟 包含 10个15分钟)# 4、自定义货币类(用于货币除法并取整)
class Currency:def __init__(self, amount, currency_code='USD'):# 初始化方法,接受货币金额和货币代码作为参数,默认为USDself.amount = float(amount)# 将货币金额转换为浮点数并存储在self.amount中self.currency_code = currency_code# 存储货币代码在self.currency_code中def __floordiv__(self, other):# 定义地板除法运算符的行为if isinstance(other, (int, float, Currency)):# 检查其他对象是否为整数、浮点数或Currency的实例if isinstance(other, Currency):# 如果其他对象是Currency的实例,则提取其金额other_amount = other.amountelse:# 如果其他对象是整数或浮点数,则将其转换为浮点数other_amount = float(other)# 使用Python内置的整数除法//来计算结果,并创建一个新的Currency对象来存储结果return Currency(self.amount // other_amount, self.currency_code)else:# 如果其他对象不是整数、浮点数或Currency的实例,则抛出TypeErrorraise TypeError(f"Unsupported operand type(s) for //: 'Currency' and '{type(other).__name__}'")def __str__(self):# 定义字符串表示方法,返回货币金额和货币代码的字符串表示return f"{self.amount} {self.currency_code}"
if __name__ == '__main__':# 创建一个Currency对象money_a,表示100.00 USDmoney_a = Currency(100.00)# 创建一个Currency对象money_b,表示20.00 USDmoney_b = Currency(20.00)# 使用地板除法运算符//计算money_a除以money_b的结果,并打印结果,预期输出: 5.0 USDprint(money_a // money_b)  # 输出: 5.0 USD (注意这里虽然用浮点数表示,但实际是整数除法)# 使用浮点数2作为除数,再次计算money_a的结果,并打印结果,预期输出: 50.0 USD# 注意这里由于self.amount是浮点数,而//是整数除法,但在Python 3中,//对于浮点数执行的是向下取整的除法print(money_a // 2)  # 输出: 50.0 USD

五、推荐阅读

1、Python筑基之旅

2、Python函数之旅

3、Python算法之旅

4、博客个人主页

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记录Win11安装打印机驱动过程

1. 首先下载打印机对应型号的驱动 可以从这里下载&#xff1a;打印机驱动,打印机驱动下载 - 打印机驱动网 2. 下载 3. 打开控制面板-->设备和打印机 找到目标打印机添加设备即可

读:《An Overview of Diffusion Models Applications……》导览

读&#xff1a;《An Overview of Diffusion Models: Applications,Guided Generation, Statistical Rates and Optimization》 简单说明 这篇文章也是关于 Diffusion 模型的综述&#xff0c;但是这一篇讲的显然不如 2022出的这篇综述 [2209.00796] Diffusion Models: A Compreh…

AI作画算法原理

1.概述 AI作画算法的原理相当复杂&#xff0c;涉及多个领域的知识&#xff0c;包括计算机视觉、机器学习和神经网络等。我们从以下几个方面来描述AI作画算法的基本原理。 2. 数据准备 在数据准备方面&#xff0c;AI作画算法通常需要大量的图像数据作为训练样本。可以是各种各…

500元以内的蓝牙耳机哪个牌子好?首推四大热门品牌盘点

在500元以内的预算范围内&#xff0c;蓝牙耳机试市场上还是有很多可以选择的&#xff0c;它们以出色的音质、舒适的佩戴体验和稳定的连接性能赢得了消费者的青睐&#xff0c;作为一个蓝牙耳机的重度使用者&#xff0c;下也用过不少的500元以内的蓝牙耳机&#xff0c;下面就给大…

Keras深度学习框架实战(1):图像分类识别

1、绪论 1.1 图像分类的定义 图像分类是计算机视觉领域中的一项基本任务&#xff0c;其定义是将输入图像分配给预定义类别中的一个或多个。具体来说&#xff0c;图像分类系统接受一个图像作为输入&#xff0c;并输出一个或多个类别标签&#xff0c;这些标签描述了图像中的内容…

基于Pytorch框架的深度学习EfficientNetV2神经网络中草药识别分类系统源码

第一步&#xff1a;准备数据 5种中草药数据&#xff1a;self.class_indict ["百合", "党参", "山魈", "枸杞", "槐花", "金银花"] &#xff0c;总共有900张图片&#xff0c;每个文件夹单独放一种数据 第二步&a…

String类详解

前言&#xff1a;String类是表示字符串的类&#xff0c;String类的内部也提供了非常多的方法来供程序员使用。 String类还有一大特性&#xff0c;就是不可变性。只要使用string创建了字符串&#xff0c;就不可以修改。为string类提供了一层安全性。&#xff08;对于" &qu…

macOS上编译android的ffmpeg及ffmpeg.c

1 前言 前段时间介绍过使用xcode和qt creator编译调试ffmepg.c&#xff0c;运行平台是在macOS上&#xff0c;本文拟介绍下android平台如何用NDK编译链编译ffmepg库并使用。 macOS上使用qt creator编译调试ffmpeg.c macOS上将ffmpeg.c编译成Framework 大体思路&#xff1a; 其…

Android Context 详解

一、什么是Context&#xff1f; Context是一个抽象基类。在翻译为上下文&#xff0c;是提供一些程序的运行环境基础信息。 Context下有两个子类&#xff0c;ContextWrapper是上下文功能的封装类&#xff08;起到方法传递的作用&#xff0c;主要实现还是ContextImpl&#xff0…

万字长文详解QUIC协议,为什么有了TCP我们还需要QUIC?

本文目录 1.前言2. HTTP缺点缺点一&#xff1a;建立连接的握手延迟大缺点二&#xff1a;多路复用的队首阻塞缺点三&#xff1a;TCP协议的更新滞后 3.TCP缺点3.QUIC优点一&#xff1a;避免队首阻塞的多路复用优点二&#xff1a;支持连接迁移优点三&#xff1a;可插拔的拥塞控制优…

【OceanBase诊断调优】—— obdiag 工具助力OceanBase数据库诊断调优(DBA 从入门到实践第八期)

1. 前言 昨天给大家分享了【DBA从入门到实践】第八期&#xff1a;OceanBase数据库诊断调优、认证体系和用户实践 中obdiag的部分&#xff0c;今天将其中的内容以博客的形式给大家展开一下&#xff0c;方便大家阅读。 2. 正文 在介绍敏捷诊断工具之前&#xff0c;先说说OceanBa…

VMware虚拟机安装Ubuntu-Server版教程(超详细)

目录 1. 下载2. 安装 VMware3. 安装 Ubuntu3.1 新建虚拟机3.2 安装操作系统 4. SSH方式连接操作系统4.1 好用的SSH工具下载&#xff1a;4.2 测试SSH连接 5. 开启root用户登录5.1 设置root用户密码5.2 传统方式切换root用户5.3 直接用root用户登录5.4 SSH启用root用户登录 6. 安…

FANUC机器人保养服务包,高效又可靠!

发那科机器人作为工业生产中的重要设备&#xff0c;其保养工作至关重要。定期FANUC机械手保养不仅可以延长机器人的使用寿命&#xff0c;还能提高生产效率和质量。 法那科机器人保养步骤&#xff1a; 基本的法兰克机器人保养是维护机器人的第一步&#xff0c;正确的保养步骤还…

Rainbond 携手 TOPIAM 打造企业级云原生身份管控新体验

TOPIAM 企业数字身份管控平台&#xff0c; 是一个开源的IDaas/IAM平台、用于管理账号、权限、身份认证、应用访问&#xff0c;帮助整合部署在本地或云端的内部办公系统、业务系统及三方 SaaS 系统的所有身份&#xff0c;实现一个账号打通所有应用的服务。 传统企业 IT 采用烟囱…

Redis用GEO实现附近的人功能

文章目录 ☃️概述☃️命令演示☃️API将数据库表中的数据导入到redis中去☃️实现附近功能 ☃️概述 GEO就是Geolocation的简写形式&#xff0c;代表地理坐标。Redis在3.2版本中加入了对GEO的支持&#xff0c;允许存储地理坐标信息&#xff0c;帮助我们根据经纬度来检索数据。…

木馒头头戴式蓝牙耳机

这里写目录标题 木馒头二代头戴式蓝牙耳机清除连接记忆 木馒头二代头戴式蓝牙耳机清除连接记忆 在配对模式下&#xff0c;同时按住播放和暂停按钮4秒&#xff0c;LED闪烁紫色3次&#xff0c;即为清除成功。

HTML动态响应2-Servlet+Ajax实现HTTP前后台交互方式

作者:私语茶馆 前言 其他涉及到的参考章节: HTML动态响应1—Ajax动态处理服务端响应-CSDN博客 Web应用JSON解析—FastJson1.2.83/Tomcat/IDEA解析案例-CSDN博客 HTML拆分与共享方式——多HTML组合技术-CSDN博客 1.场景: WEb项目经常需要前后端交互数据,并动态修改HTML页…

OSError: [Errno 117] Structure needs cleaning

一 问题描述 OSError: [Errno 117] Structure needs cleaning: /tmp/pymp-wafeatri 我重新使用SSH登录也会提示这个类似问题 二 解决方法 2.1 尝试删除报错的文件 &#xff08;想直接看最终解决方法的可忽略此处&#xff09; sudo rm -rf /tmp/pymp-wafeatri 此种方法只能保证…

【linux-imx6ull-设备树点灯】

目录 1. 设备树简介1.1 编译-引用1.2 设备树文件结构1.3 设备树节点介绍1.3.1 特殊节点chosen 1.4 节点内容追加 2. 设备树常用OF操作函数2.1 节点寻找类2.2 属性提取类2.3 其它常用类 4. 设备树下LED实验4.1 实验简介4.2 添加LED设备节点4.3 获取设备节点并提取属性4.3.1 获取…

内网渗透-隧道搭建ssp隧道代理工具

内网渗透-隧道搭建&ssp隧道代理工具 目录 内网渗透-隧道搭建&ssp隧道代理工具spp隧道代理工具spp工作原理图cs上线主机spp代理通信服务端配置客户端配置CS配置设置CS生成木马的监听器配置CS监听上线的监听器生成木马 spp隧道搭建服务端配置客户端配置CS配置 内网穿透&a…