|
前言
大家在写 Python 代码的时候有没有这样的疑问。
为什么数学中的号,在字符串运算中却酿成拼接功能,如结果为;而号酿成了重复功能,如结果为。
为什么某些对象能输出数据,而自定义的类对象却输出一堆看不懂的代码- <__main__.MyCls object at 0x105732250>
复制代码 。
不是因为系统做了特殊定制,而是 Python 中有一类特殊的方法,在某些特定的场所会自动调用。如,在字符串类中定义了方法后,当代码遇到字符串相加时,就会自动调用方法完成字符串拼接。
因为这类特殊方法的方法名都是以双下划线开始和结束,所以又被称为双下方法。
Python 中的双下方法很多,今天我们对它做个详解。
Python中的双下方法
1. init方法
的方法是很多人接触的第一个。- class A:
- def __init__(self, a):
- self.a = a
复制代码 当调用实例化对象的时候,方法会被自动调用,完成对象的初始化。
2. 运算符的双下方法
在类中定义运算符相关的,可以直接在类对象上做加减乘除、比力等操纵。
这里,定义一个尺子类,它包罗一个属性代表尺子的长度。- class Rule:
- def __init__(self, r_len):
- self.r_len = r_len
复制代码 2.1 比力运算符
如果想按照尺子的长度对差异的尺子做比力,需要在类中定义比力运算符。- class Rule:
- def __init__(self, r_len):
- self.r_len = r_len # < 运算符 def __lt__(self, other): return self.r_len < other.r_len # <= 运算符 def __le__(self, other): return self.r_len <= other.r_len # > 运算符 def __gt__(self, other): return self.r_len > other.r_len # >= 运算符 def __ge__(self, other): return self.r_len >= other.r_len
复制代码 这里定义了、、和四个比力运算符,这样就可以用下面的代码比力对象了。- rule1 = Rule(10)rule2 = Rule(5)print(rule1 > rule2) # Trueprint(rule1 >= rule2) # Trueprint(rule1 < rule2) # Falseprint(rule1 <= rule2) # False
复制代码 当用比力和的时候,对象会自动调用方法,并将对象传给参数,完成比力。
下面是比力运算符的双下方法
比力运算符双下方法
2.2 算术运算符
可以支持类对象加减乘除。- def __add__(self, other):
- return Rule(self.r_len + other.r_len)
复制代码 这里定义了方法,对应的是运算符,他会把两个尺子的长度相加,并生成新的尺子。- rule1 = Rule(10)
- rule2 = Rule(5)
- rule3 = rule1 + rule2
复制代码 下面是算术运算符的双下方法
2.3 反向算术运算符
它支持其他类型的变量与类相加。以方法为例- def __radd__(self, other):
- return self.r_len + other
复制代码- rule1 = Rule(10)
- rule2 = 10 + rule1
复制代码 步伐执行时,会实验调用类的但类类没有定义与类对象相加的方法,所以步伐会调用号右边对象的方法,并把传给参数。
所以这种运算符又叫右加运算符。它所支持的运算符与上面的算术运算符一样,方法名前加即可。
2.4 增量赋值运算符
增量赋值运算符是、、、等。- def __iadd__(self, other):
- self.r_len += other
- return self
复制代码- rule1 = Rule(10)
- rule1 += 5
复制代码 除了方法,其他的跟算数运算符一样,方面名前都加i。
2.4 位运算符
这部分支持按二进制进行取反、移位和与或非等运算。由于类不涉及位运算,所以我们换一个例子。
定义二进制字符串的类,包罗属性,表现二进制字符串。- class BinStr:
- def __init__(self, bin_str):
- self.bin_str = bin_str
复制代码- x = BinStr('1010') #创建二进制字符串对象
- print(x.bin_str) # 1010
复制代码 给定义一个取反运算符- # ~ 运算符
- def __invert__(self):
- inverted_bin_str = ''.join(['1' if i == '0' else '0' for i in self.bin_str])
- return BinStr(inverted_bin_str)
复制代码 方法中,遍历字符串,将每位取反,并返回一个新的类对象。- x = BinStr('1011')
- invert_x = ~x
- print(invert_x.bin_str) # 0100
复制代码 下面是位运算符的双下方法
这部分也支持反向位运算符和增量赋值位运算符,规则跟算数运算符一样,这里就不再赘述。
3.字符串表现
这部分涉及两个双下方法和,在某些特殊场景,如,会自动调用,将对象转成字符串。
还是以为例,先写方法。- def __repr__(self):
- decimal = int('0b'+self.bin_str, 2)
- return f'二进制字符串:{self.bin_str},对应的十进制数字:{decimal}'
复制代码- x = BinStr('1011')
- print(x)
- # 输出:二进制字符串:1011,对应的十进制数字:11
复制代码 当步伐执行时,会自动调用方法,获取对象对应的字符串。
再写方法,它也是将对象格式化为字符串。- def __format__(self, format_spec):
- return format_spec % self.bin_str
复制代码- print('{0:二进制字符串:%s}'.format(x))
- # 输出:二进制字符串:1011
复制代码 当方法的前面字符串里包罗时,就会自动调用方法,并将字符串传给参数。
4.数值转换
调用、等方法,可以将对象转成相对应数据类型的数据。- def __int__(self):
- return int('0b'+self.bin_str, 2)
复制代码- x = BinStr('1011')
- print(int(x))
复制代码 当调用时,会自动调用方法,将二进制字符串转成十进制数字。
数值转换除了上面的两个外,还有、、、、和。和一样,在时都会被自动调用,但优先级更高。
5.集合相关的双下方法
这部分可以像集合那样,定义对象长度、获取某个位置元素、切片等方法。
以和为例- def __len__(self):
- return len(self.bin_str)
- def __getitem__(self, item):
- return self.bin_str[item]
复制代码- x = BinStr('1011')
- print(len(x)) # 4
- print(x[0]) # 1
- print(x[0:3]) # 101
复制代码 会自动调用返回对象的长度。
通过方式获取对象的元素时,会自动调用方法,并将切片对象传给参数,即可以获取单个元素,还可以获取切片。
集合相关的双下方法还包罗、和。
6.迭代相关的双下方法
可以在对象上使用遍历。- def __iter__(self): self.cur_i = -1 return selfdef __next__(self): self.cur_i += 1 if self.cur_i >= len(self.bin_str): raise StopIteration() # 退出迭代 return self.bin_str[self.cur_i]
复制代码- x = BinStr('1011')
- for i in x:
- print(i)
复制代码 当在上使用循环时,会先调用方法将游标置为初始值,然后不绝调用方法遍历中的每一位。
这部分还有一个方法用来反转对象。- def __reversed__(self):
- return BinStr(''.join(list(reversed(self.bin_str))))
复制代码- x = BinStr('1011')
- reversed_x = reversed(x)
- print(reversed_x)
- # 输出:二进制字符串:1101,对应的十进制数字:13
复制代码 7.类相关的双下方法
做 web 开发的朋友,用类相关的双下方法会更多一些。
7.1 实例的创建和销毁
实例的创建是和方法,实例的销毁是方法。的调用早于,它的作用是创建对象的实例(内存开辟一段空间),而后才将该实例传给方法,完成实例的初始化。
由于是类静态方法,因此它可以控制对象的创建,从而实现单例模式。方法在实例销毁时,被自动调用,可以用来做一些清理工作和资源释放的工作。
7.2 属性管理
类属性的访问和设置。包罗、、和方法。和的区别是,当访问类属性时,无论属性存不存在都会调用方法,只有当属性不存在时才会调用方法。
7.3 属性描述符
控制属性的访问,一般用于把属性的取值控制在合理范围内。包罗、和方法。- class XValidation: def __get__(self, instance, owner): return self.x def __set__(self, instance, value): if 0 <= value <= 100: self.x = value else: raise Exception('x不能小于0,不能大于100') def __delete__(self, instance): print('删除属性')class MyCls: x = XValidation() def __init__(self, n): self.x = nobj = MyCls(10)obj.x = 101print(obj.x) # 抛异常:Exception: x不能小于0,不能大于100
复制代码 上述例子,通过类属性描述符,可以将属性x的取值控制在之前,防止不合法的取值。
8.总结
虽然上面介绍的不是所有的双下方法,但也算是绝大多数了。
虽然双下方法里可以编写任意代码,但大家尽量编写与方法要求一样的代码。如,在方法实现的不是对象相加而是相减,虽然也能运行,但这样会造成很大困惑,倒霉于代码维护。
到此这篇关于一文带你了解Python中的双下方法的文章就介绍到这了,更多相关Python双下方法内容请搜索趣UU以前的文章或继续浏览下面的相关文章希望大家以后多多支持趣UU!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|