이 기사에서는 Python에 대한 관련 지식을 제공합니다. Python에는 메서드 이름이 이중 밑줄로 시작하고 끝나는 몇 가지 특수 메서드가 있으므로 이를 함께 살펴보겠습니다. 모든 사람. 【관련 추천: Python3 동영상 튜토리얼】 머리말 파이썬 코드를 작성할 때 이런 질문이 있으신가요? 수학에서 + 기호가 'ab' + 'cd'와 같은 문자열 연산에서 연결 함수로 바뀌고 결과가 abcd; * 숫자는 'ab' * 2와 같이 반복되는 함수가 되며 결과는 abab입니다. +号,在字符串运算中却变成拼接功能,如'ab' + 'cd'结果为abcd;而*号变成了重复功能,如'ab' * 2结果为abab。 为什么某些对象print能输出数据,而print自定义的类对象却输出一堆看不懂的代码9b3ec8028913f3fbf5dd82f7dcc1bd1c。 不是因为系统做了特殊定制,而是 Python 中有一类特殊的方法,在某些特定的场合会自动调用。如,在字符串类str中定义了__add__方法后,当代码遇到字符串相加'ab' + 'cd'时,就会自动调用__add__方法完成字符串拼接。 因为这类特殊方法的方法名都是以双下划线开始和结束,所以又被称为双下方法。 Python 中的双下方法很多,今天我们对它做个详解。 Python中的双下方法 1. init方法 __init__的方法是很多人接触的第一个双下方法。class A: def __init__(self, a): self.a = a当调用A()实例化对象的时候,__init__方法会被自动调用,完成对象的初始化。 2. 运算符的双下方法 在类中定义运算符相关的双下方法,可以直接在类对象上做加减乘除、比较等操作。 这里,定义一个尺子类Rule,它包含一个属性r_len代表尺子的长度。class Rule: def __init__(self, r_len): self.r_len = r_len2.1 比较运算符 如果想按照尺子的长度对不同的尺子做比较,需要在Rule类中定义比较运算符。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这里定义了1994429935a7db9010278756f01f71bd和>=四个比较运算符,这样就可以用下面的代码比较Rule对象了。rule1 = Rule(10) rule2 = Rule(5) print(rule1 > rule2) # True print(rule1 >= rule2) # True print(rule1 < rule2) # False print(rule1 <= rule2) # False当用>比较rule1和rule2的时候,rule1对象会自动调用__gt__方法,并将rule2对象传给other参数,完成比较。 下面是比较运算符的双下方法 比较运算符双下方法 2.2 算术运算符 可以支持类对象加减乘除。def __add__(self, other): return Rule(self.r_len + other.r_len)这里定义了__add__方法,对应的是+运算符,他会把两个尺子的长度相加,并生成新的尺子。rule1 = Rule(10) rule2 = Rule(5) rule3 = rule1 + rule2下面是算术运算符的双下方法 2.3 反向算术运算符 它支持其他类型的变量与Rule类相加。以__radd__方法为例def __radd__(self, other): return self.r_len + otherrule1 = Rule(10) rule2 = 10 + rule1程序执行10 + rule1时,会尝试调用int类的__add__但int类类没有定义与Rule类对象相加的方法,所以程序会调用+号右边对象rule1的__radd__方法,并把10传给other参数。 所以这种运算符又叫右加运算符。它所支持的运算符与上面的算术运算符一样,方法名前加r即可。 2.4 增量赋值运算符 增量赋值运算符是+=、-=、*=、/=等。def __iadd__(self, other): self.r_len += other return selfrule1 = Rule(10) rule1 += 5除了__pmod__方法,其他的跟算数运算符一样,方面名前都加i。 2.4 位运算符 这部分支持按二进制进行取反、移位和与或非等运算。由于Rule类不涉及位运算,所以我们换一个例子。 定义二进制字符串的类BinStr,包含bin_str属性,表示二进制字符串。class BinStr: def __init__(self, bin_str): self.bin_str = bin_strx = BinStr('1010') #创建二进制字符串对象 print(x.bin_str) # 1010给BinStr定义一个取反运算符~일부 개체 print는 데이터를 출력할 수 있지만 print 사용자 정의 클래스 개체는 이해할 수 없는 코드 묶음을 출력하는 이유 9b3ec8028913f3fbf5dd82f7dcc1bd1c. 🎜🎜시스템을 특별히 맞춤화해서가 아니라, Python에는 특정 경우에 자동으로 호출되는 특별한 유형의 메서드가 있기 때문입니다. 예를 들어, 문자열 클래스 str에서 __add__ 메서드를 정의한 후 코드에서 문자열 추가 'ab' + 'cd'를 발견하면 __add__ 메서드는 문자열 접합을 완료하기 위해 자동으로 호출됩니다. 🎜🎜이러한 특수 메서드의 메서드 이름은 이중 밑줄로 시작하고 끝나기 때문에 이중 밑줄 메서드라고도 합니다. 🎜🎜파이썬에는 더블다운(Double-Down) 메소드가 많이 있습니다. 오늘은 이에 대해 자세히 설명하겠습니다. 🎜 🎜 Python의 더블다운 방식🎜🎜1.init 방식🎜🎜__init__ 방식은 많은 사람들이 찾아오는 첫 번째 더블 다운로드 방식입니다. 메소드와 접촉합니다. 🎜# ~ 运算符 def __invert__(self): inverted_bin_str = ''.join(['1' if i == '0' else '0' for i in self.bin_str]) return BinStr(inverted_bin_str)🎜A()를 호출하여 개체를 인스턴스화하면 __init__ 메서드가 자동으로 호출되어 개체 초기화를 완료합니다. 🎜🎜2. 연산자의 더블다운 방식🎜🎜클래스에서 덧셈, 뺄셈, 곱셈, 나눗셈, 비교 등의 연산을 직접 수행할 수 있는 연산자 관련 더블다운 방식을 정의합니다. 클래스 객체. 🎜🎜여기서 눈금자의 길이를 나타내는 r_len 속성이 포함된 눈금자 클래스 Rule을 정의하세요. 🎜x = BinStr('1011') invert_x = ~x print(invert_x.bin_str) # 0100 2.1 비교 연산자🎜 길이에 따라 서로 다른 눈금자를 비교하려면 Rule 클래스에서 비교 연산자를 정의해야 합니다. 🎜def __repr__(self): decimal = int('0b'+self.bin_str, 2) return f'二进制字符串:{self.bin_str},对应的十进制数字:{decimal}'🎜여기에는 a8a5a9aa8e3f84589d12252bdf50cac1 및 >=의 네 가지 비교가 정의되어 있습니다. 다음 코드를 사용하여 Rule 객체를 비교할 수 있도록 연산자를 사용합니다. 🎜x = BinStr('1011') print(x) # 输出:二进制字符串:1011,对应的十进制数字:11🎜>를 사용하여 rule1과 rule2를 비교하면 rule1 개체가 자동으로 를 호출합니다. __gt__ 메서드를 사용하고 rule2 개체를 other 매개변수에 전달하여 비교를 완료합니다. 🎜🎜다음은 비교연산자의 더블클릭 방식입니다🎜🎜 비교 연산자 더블다운 방식🎜 2.2 산술 연산자🎜덧셈, 뺄셈 지원 가능 , 클래스 객체의 곱셈과 나눗셈. 🎜def __format__(self, format_spec): return format_spec % self.bin_str🎜여기서 + 연산자에 해당하는 __add__ 메서드가 정의되어 있습니다. 이 메서드는 두 눈금자의 길이를 더하고 새 눈금자를 생성합니다. 🎜print('{0:二进制字符串:%s}'.format(x)) # 输出:二进制字符串:1011🎜다음은 산술연산자의 더블클릭 방법입니다🎜🎜 2.3 역산술 연산자🎜Rule 클래스를 사용하여 다른 유형의 변수 추가를 지원합니다. __radd__ 메소드를 예로 들어보세요🎜def __int__(self): return int('0b'+self.bin_str, 2)x = BinStr('1011') print(int(x))🎜프로그램이 10 + rule1을 실행할 때 의 __add__ 호출을 시도합니다. >int 클래스 그러나 int 클래스는 Rule 클래스 객체를 추가하는 메서드를 정의하지 않으므로 프로그램은 rule1+ 숫자 code>의 __radd__ 메소드 오른쪽에 10을 other에 전달합니다. 매개변수. 🎜🎜그래서 이 연산자를 오른쪽 덧셈 연산자라고도 합니다. 지원하는 연산자는 위의 산술 연산자와 동일합니다. 메소드 이름 앞에 r만 추가하면 됩니다. 🎜2.4 증분 할당 연산자🎜 증분 할당 연산자는 +=, -=, *= , /= 등 🎜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🎜__pmod__ 메서드를 제외하고 다른 모든 것은 산술 연산자와 동일하며 측면 이름 앞에 i를 추가합니다. 🎜2.4비트 연산자🎜이 부분은 부정, 시프트, AND 또는 NOT과 같은 이진 연산을 지원합니다. Rule 클래스에는 비트 연산이 포함되지 않으므로 예제를 변경해 보겠습니다. 🎜🎜바이너리 문자열을 정의하는 BinStr 클래스에는 바이너리 문자열을 나타내는 bin_str 속성이 포함되어 있습니다. 🎜def __iter__(self): self.cur_i = -1 return self def __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)🎜 BinStr에 대한 부정 연산자 ~🎜 정의# ~ 运算符 def __invert__(self): inverted_bin_str = ''.join(['1' if i == '0' else '0' for i in self.bin_str]) return BinStr(inverted_bin_str)__invert__方法中,遍历bin_str字符串,将每位取反,并返回一个新的BinStr类对象。x = BinStr('1011') invert_x = ~x print(invert_x.bin_str) # 0100下面是位运算符的双下方法 这部分也支持反向位运算符和增量赋值位运算符,规则跟算数运算符一样,这里就不再赘述。 3.字符串表示 这部分涉及两个双下方法__repr__和__format__,在某些特殊场景,如print,会自动调用,将对象转成字符串。 还是以BinStr为例,先写__repr__方法。def __repr__(self): decimal = int('0b'+self.bin_str, 2) return f'二进制字符串:{self.bin_str},对应的十进制数字:{decimal}'x = BinStr('1011') print(x) # 输出:二进制字符串:1011,对应的十进制数字:11当程序执行print(x)时,会自动调用__repr__方法,获取对象x对应的字符串。 再写__format__方法,它也是将对象格式化为字符串。def __format__(self, format_spec): return format_spec % self.bin_strprint('{0:二进制字符串:%s}'.format(x)) # 输出:二进制字符串:1011当.format方法的前面字符串里包含0:时,就会自动调用__format__方法,并将字符串传给format_spec参数。 4.数值转换 调用int(obj)、float(obj)等方法,可以将对象转成相对应数据类型的数据。def __int__(self): return int('0b'+self.bin_str, 2)x = BinStr('1011') print(int(x))当调用int(x)时,会自动调用__int__方法,将二进制字符串转成十进制数字。 数值转换除了上面的两个外,还有__abs__、__bool__、__complex__、__hash__、__index__和__str__。 __str__和__repr__一样,在print时都会被自动调用,但__str__优先级更高。 5.集合相关的双下方法 这部分可以像集合那样,定义对象长度、获取某个位置元素、切片等方法。 以__len__和__getitem__为例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]) # 101len(x)会自动调用__len__返回对象的长度。 通过[]方式获取对象的元素时,会自动调用__getitem__方法,并将切片对象传给item参数,即可以获取单个元素,还可以获取切片。 集合相关的双下方法还包括__setitem__、__delitem__和__contains__。 6.迭代相关的双下方法 可以在对象上使用for-in遍历。def __iter__(self): self.cur_i = -1 return self def __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)当在x上使用for-in循环时,会先调用__iter__方法将游标cur_i置为初始值-1,然后不断调用__next__方法遍历self.bin_str中的每一位。 这部分还有一个__reversed__方法用来反转对象。def __reversed__(self): return BinStr(''.join(list(reversed(self.bin_str))))x = BinStr('1011') reversed_x = reversed(x) print(reversed_x) # 输出:二进制字符串:1101,对应的十进制数字:137.类相关的双下方法 做 web 开发的朋友,用类相关的双下方法会更多一些。 7.1 实例的创建和销毁 实例的创建是__new__和__init__方法,实例的销毁是__del__方法。 __new__的调用早于__init__,它的作用是创建对象的实例(内存开辟一段空间),而后才将该实例传给__init__方法,完成实例的初始化。 由于__new__是类静态方法,因此它可以控制对象的创建,从而实现单例模式。 __del__方法在实例销毁时,被自动调用,可以用来做一些清理工作和资源释放的工作。 7.2 属性管理 类属性的访问和设置。包括__getattr__、__getattribute__、__setattr__和__delattr__方法。 __getattr__和__getattribute__的区别是,当访问类属性时,无论属性存不存在都会调用__getattribute__方法,只有当属性不存在时才会调用__getattr__方法。 7.3 属性描述符 控制属性的访问,一般用于把属性的取值控制在合理范围内。包括__get__、__set__和__delete__方法。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 = n obj = MyCls(10) obj.x = 101 print(obj.x) # 抛异常:Exception: x不能小于0,不能大于100上述例子,通过类属性描述符,可以将属性x的取值控制在[0, 100]之前,防止不合法的取值。 8.总结 虽然上面介绍的不是所有的双下方法,但也算是绝大多数了。 虽然双下方法里可以编写任意代码,但大家尽量编写与方法要求一样的代码。如,在__add__方法实现的不是对象相加而是相减,虽然也能运行,但这样会造成很大困惑,不利于代码维护。 【相关推荐:Python3视频教程 】