Cet article vous apporte des connaissances pertinentes sur Python. Il existe des méthodes spéciales en Python dont les noms de méthode commencent et se terminent par des traits de soulignement doubles, elles sont donc également appelées méthodes à double soulignement. tout le monde. 【Recommandation connexe : Tutoriel vidéo Python3】 Avant-propos Avez-vous de telles questions lorsque vous écrivez du code Python ? Pourquoi le signe + en mathématiques est-il transformé en fonction de concaténation dans les opérations sur les chaînes, telles que 'ab' + 'cd' et le résultat est abcd; et le nombre * devient une fonction répétée, telle que 'ab' * 2, le résultat est 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定义一个取反运算符~Pourquoi certains objets print peuvent générer des données, mais les objets de classe personnalisés print génèrent un tas de code incompréhensible c808ec958b06ce1072a719a3761f5713. 🎜🎜Ce n'est pas parce que le système a été spécialement personnalisé, mais parce qu'il existe un type spécial de méthode en Python qui est automatiquement appelée à certaines occasions. Par exemple, après avoir défini la méthode __add__ dans la classe de chaîne str, lorsque le code rencontre l'ajout de chaîne 'ab' + 'cd' , le La méthode __add__ sera automatiquement appelée pour terminer l'épissage des chaînes. 🎜🎜Étant donné que les noms de méthodes de ce type de méthodes spéciales commencent et se terminent par des traits de soulignement doubles, elles sont également appelées méthodes à double trait de soulignement. 🎜🎜Il existe de nombreuses méthodes de double téléchargement en Python Aujourd'hui, nous allons l'expliquer en détail. 🎜 🎜 Méthode de double téléchargement en Python🎜🎜1. Méthode d'initialisation🎜🎜La méthode __init__ est la première méthode de double téléchargement à laquelle de nombreuses personnes viennent. en contact avec la Méthode. 🎜# ~ 运算符 def __invert__(self): inverted_bin_str = ''.join(['1' if i == '0' else '0' for i in self.bin_str]) return BinStr(inverted_bin_str)🎜Lors de l'appel de A() pour instancier un objet, la méthode __init__ sera automatiquement appelée pour terminer l'initialisation de l'objet. 🎜🎜2. Méthode de double-down de l'opérateur🎜🎜Définissez la méthode de double-down liée à l'opérateur dans la classe, qui peut effectuer directement des opérations d'addition, de soustraction, de multiplication, de division, de comparaison et d'autres opérations sur le objet de classe. 🎜🎜Ici, définissez une classe de règle Rule, qui contient un attribut r_len pour représenter la longueur de la règle. 🎜x = BinStr('1011') invert_x = ~x print(invert_x.bin_str) # 0100 2.1 Opérateurs de comparaison🎜Si vous souhaitez comparer différentes règles en fonction de leur longueur, vous devez définir des opérateurs de comparaison dans la classe Rule. 🎜def __repr__(self): decimal = int('0b'+self.bin_str, 2) return f'二进制字符串:{self.bin_str},对应的十进制数字:{decimal}'🎜Quatre comparaisons sont définies ici : a8a5a9aa8e3f84589d12252bdf50cac1 et >= afin que vous puissiez comparer les objets Rule à l'aide du code suivant. 🎜x = BinStr('1011') print(x) # 输出:二进制字符串:1011,对应的十进制数字:11🎜Lorsque vous utilisez > pour comparer rule1 et rule2, l'objet rule1 appellera automatiquement __gt__ et transmettez l'objet rule2 au paramètre other pour terminer la comparaison. 🎜🎜Ce qui suit est la méthode du double-clic de l'opérateur de comparaison🎜🎜 Méthode de double-down de l'opérateur de comparaison🎜 2.2 Opérateur arithmétique🎜Peut prendre en charge l'addition, la soustraction , multiplication et division des objets de classe . 🎜def __format__(self, format_spec): return format_spec % self.bin_str🎜La méthode __add__ est définie ici, correspondant à l'opérateur + Elle ajoutera les longueurs des deux règles et générera une nouvelle règle. 🎜print('{0:二进制字符串:%s}'.format(x)) # 输出:二进制字符串:1011🎜Ce qui suit est la méthode du double-clic des opérateurs arithmétiques🎜🎜 2.3 Opérateur arithmétique inverse🎜Il prend en charge l'ajout d'autres types de variables avec la classe Rule. Prenons l'exemple de la méthode __radd__🎜def __int__(self): return int('0b'+self.bin_str, 2)x = BinStr('1011') print(int(x))🎜Lorsque le programme exécute 10 + règle1, il essaiera d'appeler le __add__ du int Cependant, la classe int ne définit pas de méthode pour ajouter l'objet de classe Rule, le programme appellera donc l'objet rule1+ code> de la méthode __radd__, et passez 10 à l'autre. paramètre. 🎜🎜Cet opérateur est donc également appelé opérateur d'addition de droite. Les opérateurs qu'il prend en charge sont les mêmes que les opérateurs arithmétiques ci-dessus. Ajoutez simplement r avant le nom de la méthode. 🎜2.4 Opérateur d'affectation incrémentielle🎜Les opérateurs d'affectation incrémentielle sont +=, -=, *= , /=, etc. 🎜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🎜À l'exception de la méthode __pmod__, tout le reste est identique aux opérateurs arithmétiques, avec i ajouté avant le nom de l'aspect. 🎜Opérateurs 2,4 bits🎜Cette partie prend en charge les opérations binaires telles que la négation, le décalage, ET ou NON. Puisque la classe Rule n'implique pas d'opérations sur les bits, changeons d'exemple. 🎜🎜La classe BinStr qui définit une chaîne binaire contient l'attribut bin_str, qui représente une chaîne binaire. 🎜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)🎜Définissez un opérateur de négation ~🎜 pour 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视频教程 】