• Python 魔法方法


    Python 魔法方法

    基础:

    如果你想…所以,你写…Python调用…
    初始化一个实例 x = MyClass() x.__init__()
    作为一个字符串的"官方"表示 repr(x) x.__repr__()
    作为一个字符串 str(x) x.__str__()
    作为字节数组 bytes(x) x.__bytes__()
    作为格式化字符串 format(x, format_spec) x.__format__(format_spec)
    • __init__()方法在创建实例后调用.如果你想控制创建过程,请使用__new__()方法
    • 按照惯例, __repr__() 应该返回一个有效的Python表达式的字符串
    • __str__()方法也被称为你的print(x)

    迭代相关

    如果你想…所以,你写…Python调用…
    遍历一个序列 iter(seq) seq.__iter__()
    从迭代器中获取下一个值 next(seq) seq.__next__()
    以相反的顺序创建一个迭代器 reversed(seq) seq.__reversed__()
    • __iter__()无论何时创建新的迭代器,都会调用该方法.
    • __next__()每当你从迭代器中检索一下个值的时候,都会调用该方法
    • __reversed__()方法并不常见.它需要一个现有序列并返回一个迭代器,该序列是倒序的顺序.

    属性

    如果你想…所以,你写…Python调用…
    得到一个属性 x.my_property x.__getattribute__('my_property')
    获得一个属性 x.my_property x.__getattr__('my_property')
    设置一个属性 x.my_property = value x.__setattr__('my_property', value)
    删除一个属性 del x.my_property x.__delattr__('my_property')
    列出所有属性和方法 dir(x) x.__dir__()
    • 如果你的类定义了一个__getattribute__()方法,Python将在每次引用任何属性或方法名时调用它.
    • 如果你的类定义了一个__getattr__()方法,Python只会在所有普通地方查找属性后调用它.如果一个实例x定义了一个属性 colorx.color将不会调用x.__getattr__('color'); 它将简单地返回已经定义的x.color值.
    • __setattr__()只要你为属性指定值,就会调用该方法.
    • __delattr__()只要删除属性,就会调用该方法.
    • __dir__()如果您定义一个__getattr__() 或者 __getattribute__() 方法,该方法很有用.通常情况下,调用dir(x)只会列出常规属性和方法.

    __getattr__()__getattribute__()方法之间的区别很微妙但很重要.

    函数类

    通过定义__call__()方法,您可以创建一个可调用类的实例 - 就像函数可调用一样.

    如果你想…所以,你写…Python调用…
    来"调用"像函数一样的实例 my_instance() my_instance.__call__()

    行为

    如果你的类作为一组值的容器 - 也就是说,如果问你的类是否"包含"一个值是有意义的 - 那么它应该定义下面的特殊方法,使它像一个集合一样.

    如果你想…所以,你写…Python调用…
    序列的数量 len(s) s.__len__()
    否包含特定的值 x in s s.__contains__(x)

    字典(映射)

    如果你想…所以,你写…Python调用…
    通过它的key来获得值 x[key] x.__getitem__(key)
    通过它的key来设置一个值 x[key] = value x.__setitem__(key, value)
    删除键值对 del x[key] x.__delitem__(key)
    为丢失的key提供默认值 x[nonexistent_key] x.__missing__(nonexistent_key)

    数字

    如果你想…所以,你写…Python调用…
    x + y x.__add__(y)
    x - y x.__sub__(y)
    x * y x.__mul__(y)
    整除 x / y x.__trueiv__(y)
    x // y x.__floordiv__(v)
    取余 x % y x.__mod__(y)
    整除与取余 divmod(x, y) x.__divmod__(y)
    平方 x ** y x.__pow__(y)
    左移 x << y x.__lshift__(y)
    右移 x >> y x.__rshift__(y)
    按位and运算 x & y x.__and__(y)
    按位xor或运算 x ^ y x.__xor__(y)
    按位or运算 x | y x.__or__(y)

    上述一组特殊方法采用第一种方法:给定x / y,它们提供了一种方法让x说"我知道如何用y整除自己".以下一组特殊方法解决了第二种方法:它们为y提供了一种方法来说"我知道如何成为分母,并将自己整除x".

    如果你想…所以,你写…Python调用…
    x + y x.__radd__(y)
    x - y x.__rsub__(y)
    x * y x.__rmul__(y)
    整除 x / y x.__rtrueiv__(y)
    x // y x.__rfloordiv__(v)
    取余 x % y x.__rmod__(y)
    整除与取余 divmod(x, y) x.__rdivmod__(y)
    平方 x ** y x.__rpow__(y)
    左移 x << y x.__rlshift__(y)
    右移 x >> y x.__rrshift__(y)
    按位and运算 x & y x.__rand__(y)
    按位xor或运算 x ^ y x.__rxor__(y)
    按位or运算 x | y x.__ror__(y)

    可是等等!还有更多!如果你正在进行"就地"操作,如x /= 3则可以定义更多特殊的方法.

    如果你想…所以,你写…Python调用…
    x + y x.__iadd__(y)
    x - y x.__isub__(y)
    x * y x.__imul__(y)
    整除 x / y x.__itrueiv__(y)
    x // y x.__ifloordiv__(v)
    取余 x % y x.__imod__(y)
    整除与取余 divmod(x, y) x.__idivmod__(y)
    平方 x ** y x.__ipow__(y)
    左移 x << y x.__ilshift__(y)
    右移 x >> y x.__irshift__(y)
    按位and运算 x & y x.__iand__(y)
    按位xor或运算 x ^ y x.__ixor__(y)
    按位or运算 x | y x.__ior__(y)

    还有一些"单个数"数学运算可以让你自己对类似数字的对象进行数学运算.

    如果你想…所以,你写…Python调用…
    负数 -x x.__neg__()
    正数 +x x.__pos__()
    绝对值 abs(x) x.__abs__()
    ~x x.__invert__()
    复数 complex(x) x.__complex__()
    整数 int(x) x.__int__()
    浮点数 float(x) x.__float__()
    四舍五入到最近的整数 round(x) x.__round__()
    四舍五入到最近的n位数 round(x, n) x.__round__(n)
    最小整数 math.ceil(x) x.__ceil__()
    最大整数 math.floor(x) x.__floor__()
    截断x到0的最接近的整数 math.trunc(x) x.__trunc__()
    数字作为列表索引 a_list[x] a_list[x.__index__()]

    比较

    如果你想…所以,你写…Python调用…
    等于 x == y x.__eq__(y)
    不等于 x != y x.__ne__(y)
    小于 x < y x.__lt__(y)
    小于等于 x <= y x.__le__(y)
    大于 x > y x.__gt__(y)
    大于等于 x >= y x.__ge__(y)
    布尔 if x: x.__bool__()

    序列化

    如果你想…所以,你写…Python调用…
    对象副本 copy.copy(x) x.__copy__()
    深拷贝 copy.deepcopy(x) x.__deepcopy__()
    序列化一个对象 pickle.dump(x, file) x.__getstate__()
    序列化一个对象 pickle.dump(x, file) x.__reduce__()
    序列化一个对象 pickle.dump(x, file, protocol_version) x.__reduce_ex__(protocol_version)
    取出恢复后的状态 x = pickle.load(fp) x.__getnewargs__()
    取出恢复后的状态 x = pickle.load(fp) x.__setstate__()

    with 语句

    with块限定了运行时上下文;在执行with语句时,"进入"上下文,并在执行块中的最后一个语句后"退出"上下文.

    如果你想…所以,你写…Python调用…
    进入with语句块 with x: x.__enter__()
    退出with语句块 with x: x.__exit__(exc_type, exc_value, traceback)

    真正深奥的东西

    如果你想…所以,你写…Python调用…
    一个类的构造函数 x = MyClass() x.__new__()
    一个类的析构函数 del x x.__del__()
    只有一组特定的属性需要定义 `` x.__slots__()
    hash码 hash(x) x.__hash__()
    获得一个属性的值 x.color type(x).__dict__['color'].__get__(x, type(x))
    设置一个属性的值 x.color = 'PapayaWhip' type(x).__dict__['color'].__set__(x, 'PapayaWhip')
    删除一个属性 del x.color type(x).__dict__['color'].__del__(x)
    一个对象是否是你的一个类的实例 isinstance(x, MyClass) MyClass.__instancecheck__(x)
    一个类是否是你的类的子类 isinstance(C, MyClass) MyClass.__subclasscheck__(C)
    一个类是否是抽象基类的实例 isinstance(C, MyABC) MyABC.__subclasshook__(C)

    Python正确调用__del__()特殊方法时非常复杂.为了完全理解它,你需要知道Python如何跟踪内存中的对象.这里有一篇关于 Python垃圾收集和类析构函数的好文章.你还应该阅读关于弱引用,weakref模块,以及可能的gc模块以获得更好的度量.

  • 相关阅读:
    237. Delete Node in a Linked List
    430. Flatten a Multilevel Doubly Linked List
    707. Design Linked List
    83. Remove Duplicates from Sorted List
    160. Intersection of Two Linked Lists
    426. Convert Binary Search Tree to Sorted Doubly Linked List
    142. Linked List Cycle II
    类之间的关系
    初始化块
    明确类和对象
  • 原文地址:https://www.cnblogs.com/pyse/p/9099290.html
Copyright © 2020-2023  润新知