User:Xyy23330121/Python/类的方法与Python的计算


学习了“类”之后,我们可以进一步了解 Python 的数据模型:Python 中一切内容、包括计算在内,都是由类和类的实例完成的。

以简单的 len(s) 为例,我们查阅文档,可以发现它实际上是调用了 s 的方法 s.__len__(self),并返回该方法的结果[1]

甚至,连加减法在内,几乎所有的 Python 运算都可以用类的方法来定义、修改。为篇幅起见,本页面的内容被分为多个页面。读者可以在右侧目录中找到对应页面。

可调用类型

编辑

object.__call__(self[, ...])

编辑

此方法用于支持把对象当函数使用时的结果。我们看以下示例:

class prt:
    def __call__(self, *arg):
        print(*arg)

a = prt()
a(11,45,14)  #输出:11 45 14

它除了第一个参数会自动传入自身以外,与平常定义的函数基本没有区别。

容器类型

编辑

长度

编辑
备注
读者想要让它不返回对象的长度,而是返回其他内容也是可以的,只是这样的话,在使用 len 函数时可能会产生困惑。

object.__len__(self)[1]

编辑

此方法用于支持 len(self)。该方法必须返回对象的长度,并必须以一个非负的 int 类型来表示。如果返回的并非非负整数,则会报错。

特别的,如果一个对象没有定义 __bool__方法,而其 __len__ 方法返回的值为 0。则它在布尔运算中,被视为 False

object.__length_hint__(self)[2]

编辑

operator 模块中,operator.length_hint()函数所调用的方法。

此方法是为了优化性能而设置的,它必须返回对象长度的估计值——这个估计值并不要求正确无误。返回的估计值必须为一个非负整数。

特别的,返回值也可以为 NotImplemented,这会被视作与 __length_hint__ 方法完全不存在时一样处理。

索引

编辑

object.__getitem__(self, key)

编辑

此方法用于支持 self[key] 的操作。一般用于键的有三种:

  1. 整数(用于序列)
  2. slice 对象(用于序列)
  3. 字符串或其它不可变对象(主要用于字典)。

此方法的返回值,应当为读者希望 self[key] 所返回的数值。和其它强制进行类型检查的方法不同,此方法实际上可以返回任何值。

object.__setitem__(self, key, value)

编辑

此方法用于支持 self[key] = value 的操作。在调用此方法时,应直接对 self 进行修改。

object.__delitem__(self, key)

编辑

此方法用于支持 del self[key] 的操作。

slice 对象

编辑

在字符串章节,提到过 slice 索引。slice 对象就是用该种索引方式时,向 key 参数传入的对象。

索引与错误处理

编辑

如果 key 的类型不正确,则应当引发 TypeError。 如果 key 为序列索引集合范围以外的值(在进行任何负数索引的特殊解读之后),则应当引发 IndexError。 对于 mapping 类型,如果 key 找不到(不在容器中),则应当引发 KeyError。

解决 str.format 的问题

编辑

于是,解决 str.format 中,不支持负数索引和 slice 索引的方式是简单的。使用:

class fixGetitem:
    def __init__(self, obj):
        self.obj = obj
    def __getitem__(self, key):
        if isinstance(key, str):
            if ':' in key:
                key_list = [(int(arg) if arg != "" else None) for arg in key.split(':')]
                if len(key_list) == 2:
                    return self.obj[key_list[0]: key_list[1]]
                return self.obj[key_list[0]: key_list[1]: key_list[2]]
            return self.obj[int(key)]
        return self.obj[key]

在传入 str.format 的参数 s 时,如果有负数索引或 slice 索引的需要(且没有字符串索引的需要时),直接改为传入 fixGetitem(s) 就能解决该问题。读者可以自行拓展此方法。

object.__missing__(self, key)

编辑

对于 dict 的子类,如果定义了该方法。则在 __getitem__(key) 找不到键 key 时,会尝试调用 __missing__(key) 并返回 __missing__(key) 的值。

迭代

编辑

object.__iter__(self)

编辑

该方法应该且必须返回一个新的迭代器对象。如果不返回迭代器,则会报错。

此方法可用于支持 iter 函数、for ... in 语句以及比较运算符 innot in

object.__reversed__(self)

编辑

该方法用于提升 reversed(self) 的效率和 / 或适用范围。

如果定义了该方法,则该方法必须返回一个新的迭代器对象。它应当返回以逆序逐个迭代容器内所有对象的迭代器对象。

如果未定义该方法,则 reversed(self) 会使用 __len__ 方法和 __getitem__ 方法,按照类似列表的方式生成一个迭代器。

成员检测

编辑

object.__contains__(self, item)

编辑

此方法用于支持 item in selfitem not in self。它返回一个布尔值。

如果未定义 __contains__ 方法。上述运算将尝试通过 __iter__ 来迭代 self 中的元素来实现。

泛型

编辑

对于类型,我们也有类似索引的操作。泛型就是这种操作的结果。

泛型一般用于函数注释中。具体参见 函数注释#泛型

classmethod object.__class_getitem__(cls, key)

编辑

获取泛型时调用的方法。这个方法会自动被视为是类方法,因此没必要使用装饰符 @classmethod 来装饰。

此方法一般不由读者定义,而是通过继承的方式自动引入的。具体可以参见Python 文档

參考文獻

编辑