• 技术文章 >后端开发 >Python教程

    完全掌握Python中的双下方法

    长期闲置长期闲置2022-07-21 17:50:37转载565
    本篇文章给大家带来了关于Python的相关知识,Python中有一些特殊方法的方法名都是以双下划线开始和结束,所以又被称为双下方法,下面一起来看一下,希望对大家有帮助。

    【相关推荐:Python3视频教程

    前言

    大家在写 Python 代码的时候有没有这样的疑问。

    为什么数学中的+号,在字符串运算中却变成拼接功能,如'ab' + 'cd'结果为abcd;而*号变成了重复功能,如'ab' * 2结果为abab

    为什么某些对象print能输出数据,而print自定义的类对象却输出一堆看不懂的代码<__main__.MyCls object at 0x105732250>

    不是因为系统做了特殊定制,而是 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_len

    2.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

    这里定义了<<=>>=四个比较运算符,这样就可以用下面的代码比较Rule对象了。

    rule1 = Rule(10)
    rule2 = Rule(5)
    print(rule1 > rule2)  # True
    print(rule1 >= rule2)  # True
    print(rule1 < rule2)  # False
    print(rule1 <= rule2)  # False

    当用>比较rule1rule2的时候,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 + other
    rule1 = 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 self
    rule1 = Rule(10)
    rule1 += 5

    除了__pmod__方法,其他的跟算数运算符一样,方面名前都加i。

    2.4 位运算符

    这部分支持按二进制进行取反、移位和与或非等运算。由于Rule类不涉及位运算,所以我们换一个例子。

    定义二进制字符串的类BinStr,包含bin_str属性,表示二进制字符串。

    class BinStr:
        def __init__(self, bin_str):
            self.bin_str = bin_str
    x = BinStr('1010')  #创建二进制字符串对象
    print(x.bin_str) # 1010

    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_str
    print('{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])  # 101

    len(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,对应的十进制数字:13

    7.类相关的双下方法

    做 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视频教程

    以上就是完全掌握Python中的双下方法的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:脚本之家,如有侵犯,请联系admin@php.cn删除
    专题推荐:python
    上一篇:Python解析参数的三种方法详解 下一篇:Python中闭包与lambda的作用域解析
    VIP课程(WEB全栈开发)

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• python网络爬虫方向的第三方库有哪些• 一文搞懂Python爬虫解析器BeautifulSoup4• python虚拟环境配置与管理• 一文搞懂怎么在python中读取和写入CSV文件• 实例分享8个Python自动化脚本
    1/1

    PHP中文网