chapter9.1、魔术方法

泄露秘密 提交于 2020-02-24 05:51:09

魔术方法

python精华之一

特殊属性

__name__ 类,函数,方法等的名字
__modle__ 主模块,当前的模块__main__,其他模块调用返回模块对象
__class__ 相当于type,对象或类所属的类
__bases__ 返回基类的元组,顺序为基类列表中出现的顺序
__doc__ 文档,未定义为None
__mro__ 类的mro,定义时就会计算并放在类的属性里的__mro__中
__dict__ 类或实例的属性,可写的字典,这里注意有些只读字典

查看属性

__dir__ 返回类的或者对象的所有成员的列表,

dir()函数调用__dir__(),dir是内建函数,

如果类中和实例中定义了__dir__:

  使用实例调用时,实例中如果定义了__dir__,就会覆盖类__dir__,返回实例中的__dir__的运行结果;

  如果实例中没有,就会调用父类的,如果父类没有,就继续向上找,中间有的话就会运行该方法;

如果类中和实例中没有定义__dir__:

  如果对象是模块对象,返回的列表包含文件的属性名和变量名,受作用域影响,一般在模块上使用时,调用模块,在自己的模块搜集

  如果对象是类或类的实例,近似于自己实例的字典加类的字典加object的字典,返回列表包含类的属性名,及它的基类的属性名

  如果dir()    括号中不写,返回的列表包含不同的内容

    在模块中,返回模块的属性和变量名

    在函数中,返回本地作用域的变量名

    在函数中,返回本地作用域的变量名

 

魔术方法 

创建,初始化与销毁

    __new__ 实例化,可以不写,会去调父类的方法。一定要return,返回不要再调自己,调本类型的实例,如果不是cls的实例,就不会调用__init__,即使创建了该方法,也会使用return super().__new__(cls), 最后调用的是object的__new__方法创建并返回实例

    __init__

    __del__
__hash__  内建函数hash()调用后的返回值,返回整数,现在Linux的加密主要使用的MD5算法也是hash算法的一种,

  哈希算法,具有幂等性,同一个程序中不论计算多少次,相同的对象返回的hash的值都一样,

  不同的hash算法,可能会产生hash冲突,不同的x可能求得同样的值

__eq__ 判断是否相同,返回一个bool值,hash函数只负责计算hash,去重需要__eq__判断,

  一般hash只要不冲突,就不会调用__eq__,__eq__ 对应  '=='  操作符,判断两个对象是否相等,返回bool。

  一旦类中提供__eq__ ,类中就会自动添加__hash__=None

  hash值相等不代表对象相等,

  list类的实例不可hash,在list类中,源码中有__hash__ = None,也就是说如果调用__hash__相当于调用None,

  如果你创建的类不能被hash,那就把__hash__设置为None

import math

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def  __hash__(self):
        return  hash((self.x, self.y))

    def __eq__(self, obj):
        return self.x == obj.x and self.y == obj.y

p1 = Point(3, 0)
p2 = Point(0, 4)
p3 = Point(3, 0)
print({p1, p2, p3})##可以去重

 

__bool__    内建函数bool(),或者对象放在逻辑表达式的位置,调用这个函数返回布尔值

  没有定义__bool__()的,就去__len__()返回长度,非零为真

可视化方法

__repr__ 内建函数repr()对一个对象获取字符串表达,

  调用__repr__方法返回字符串,间接调用会调,如果未定义,直接返回object的定义,也就是显示内存地址的信息

__str__ 实例直接print(),或者str(),或者format(),调用时,要返回对象的字符串表达,

  如果没有定义,就去调用__repr__方法返回字符串表达式,如果没有__repr__定义,就直接返回对象的内存地址

  类不提供__str__,就使用__repr__;不提供__repr__就去object找,

  要注意:打印对象,输出形式,打印出来的类型不作数,并不能真正的表达对象的类型!

__bytes__ 提供bytes方法,bytes()函数调用,返回一个对象的bytes表达,即返回bytes对象

 

运算符重载

<  __lt__    小于    lessthan

<=  __le__    小于等于    lessequal

>  __gt__    大于    greatthan 

>=  __ge__    大于等于    greatequal

==  __eq__    等于    equal   ,只有==才调用

!=  __ne__  不等于    notequal

+ - * /  __add__ ,__sub__ ,__mul__ ,__truediv__ 加减乘除重载

%  __mod__  取模运算重载

//  __floordiv__  整除重载

**  __pow__  乘方重载

divmod  __divmod__        取模取余

+= ,-= , *= , /= , %= , //= , **=    __iadd__ , __isub__ , __imul__ , itruediv__ , __imod__ , __ifloordiv__ , __ipow__   ,其中的 i 表示in place,立即返回

如果不定义加等,就去调add,在赋值给左边的值,其他的运算也是

实例之间的计算,可以用坐标点来理解

import mathclass Point:
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def __eq__(self,obj):
        return self.x ==obj.x and self.y == obj.y

    def __add__(self,other):
        return Point(self.x + other.x,self.y+other.y)

    def __sub__(self,other):
        return Point(self.x - other.x,self.y-other.y)

    def __repr__(self):
        return "({},{})".format(self.x,self.y)

 

还可以使用total ordering 模块,但是要提供等于和大小与四种之中的一种,一般自己写,写三个,等于,大小于中的一个,和大于小于中的一个,就可以推断另一个

大于推断小于

等于推断不等于

大于等于推断小于等于

 用total ordering 可能产生性能问题,尽量自己写,

类的大量运算,运算符是较常见的表达方式,提供运算符重载比提供加法方式更符合使用者的习惯

可参见int的所有的操作符,几乎实现了所有的操作符

容器相关方法

__len__  内建函数len(),返回对象的长度(>=0),将对象看作容器,bool()函数调用时,没有__bool__属性时,就会来判断__len__是否存在,如果存在且不为0,就返回真

__iter__  迭代容器内容时,返回一个迭代器对象

__contains__  in成员运算符,没有实现,就调__iter__遍历,查找都要遍历,可以不写contains

__getitem__  实现self [ key ] 访问,如果是序列对象,key就是整数索引,或者是切片,对于字典和集合,key是hashable的,不存在就KeyError

__setitem__  和getitem访问类似,是设置值的方法

__missing__  字典和类使用时,__getitem__()调用key不存在时执行

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!