User:Xyy23330121/Python/类的方法与Python的计算
学习了“类”之后,我们可以进一步了解 Python 的数据模型:Python 中一切内容、包括计算在内,都是由类和类的实例完成的。
以简单的 len(s)
为例,我们查阅文档,可以发现它实际上是调用了 s
的方法 s.__len__(self)
,并返回该方法的结果[1]。
甚至,连加减法在内,几乎所有的 Python 运算都可以用类的方法来定义、修改。为篇幅起见,本页面的内容被分为多个页面。读者可以在右侧目录中找到对应页面。
此方法用于支持把对象当函数使用时的结果。我们看以下示例:
class prt:
def __call__(self, *arg):
print(*arg)
a = prt()
a(11,45,14) #输出:11 45 14
它除了第一个参数会自动传入自身以外,与平常定义的函数基本没有区别。
len
函数时可能会产生困惑。此方法用于支持 len(self)
。该方法必须返回对象的长度,并必须以一个非负的 int
类型来表示。如果返回的并非非负整数,则会报错。
特别的,如果一个对象没有定义 __bool__
方法,而其 __len__
方法返回的值为 0
。则它在布尔运算中,被视为 False
。
operator
模块中,operator.length_hint()
函数所调用的方法。
此方法是为了优化性能而设置的,它必须返回对象长度的估计值——这个估计值并不要求正确无误。返回的估计值必须为一个非负整数。
特别的,返回值也可以为 NotImplemented,这会被视作与 __length_hint__ 方法完全不存在时一样处理。
此方法用于支持 self[key]
的操作。一般用于键的有三种:
- 整数(用于序列)
- slice 对象(用于序列)
- 字符串或其它不可变对象(主要用于字典)。
此方法的返回值,应当为读者希望 self[key]
所返回的数值。和其它强制进行类型检查的方法不同,此方法实际上可以返回任何值。
此方法用于支持 self[key] = value
的操作。在调用此方法时,应直接对 self
进行修改。
此方法用于支持 del self[key]
的操作。
在字符串章节,提到过 slice 索引。slice 对象就是用该种索引方式时,向 key
参数传入的对象。
如果 key 的类型不正确,则应当引发 TypeError。 如果 key 为序列索引集合范围以外的值(在进行任何负数索引的特殊解读之后),则应当引发 IndexError。 对于 mapping 类型,如果 key 找不到(不在容器中),则应当引发 KeyError。
于是,解决 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)
就能解决该问题。读者可以自行拓展此方法。
对于 dict 的子类,如果定义了该方法。则在 __getitem__(key)
找不到键 key
时,会尝试调用 __missing__(key)
并返回 __missing__(key)
的值。
该方法应该且必须返回一个新的迭代器对象。如果不返回迭代器,则会报错。
此方法可用于支持 iter
函数、for ... in
语句以及比较运算符 in
和 not in
。
该方法用于提升 reversed(self)
的效率和 / 或适用范围。
如果定义了该方法,则该方法必须返回一个新的迭代器对象。它应当返回以逆序逐个迭代容器内所有对象的迭代器对象。
如果未定义该方法,则 reversed(self)
会使用 __len__
方法和 __getitem__
方法,按照类似列表的方式生成一个迭代器。
此方法用于支持 item in self
和 item not in self
。它返回一个布尔值。
如果未定义 __contains__
方法。上述运算将尝试通过 __iter__
来迭代 self
中的元素来实现。
对于类型,我们也有类似索引的操作。泛型就是这种操作的结果。
泛型一般用于函数注释中。具体参见 函数注释#泛型 。
获取泛型时调用的方法。这个方法会自动被视为是类方法,因此没必要使用装饰符 @classmethod
来装饰。
此方法一般不由读者定义,而是通过继承的方式自动引入的。具体可以参见Python 文档。