读书笔记之Python进阶指南 序列的修改、散列和切片 fluent Python

第十章 序列的修改、散列和切片

1.切片是一个对象
slice(start, stop, stride)
它还有一个.indices(n)的方法,能优雅地处理过界与索引丢失
如:
slice(None, 10, 2).indices(5) #说明这个切片长度为5
然后切片就会变成slice(0, 5, 2)


2.判断是不是数字
用isinstance(a, numbers.integral) 判断是不是整型

3.目前我们vector类很大,并且不支持v1.x去访问x方向上的分量,但我们又想做到,怎么实现呢?

通过__getattr__方法:

    shortcut_names = "xyzt"
    def __getattr__(self, name):
        cls = type(self)
        if len(name) == 1:
            pos = cls.shortcut_names.find(name)
            if 0 <= pos <len(self.components):
                return self._components[pos]
        msg = '{.__name__!r} object has no attribute {!r}'
        raise AttributeError(msg.format(cls, name))

但我们又不想这样去让他赋值,通过__setattr__:

    def __setattr__(self, name, value):
        cls = type(self)
        if len(name) == 1:
            if name in cls.shortcut_names:
                error = 'readonly attributes {attr_name!r}'
            elif name.islower():
                error = "can't set attribues 'a' to 'z' in {cls_name!r}"

            else:
                error = ''
            if error:
                raise ArithmeticError(error.format(cls_name=cls.__name__, attr_name=name))
            super().__setattr__(name, value)

这告诉我们实现了getattr 后通常要实现setattr


4.接下来是比较牛逼的技术了

因为我们要让我们这个类变得散列,所以我们得实现hash方法

请看如何实现的

    def __hash__(self):
        coord = (hash(x) for x in self._components)
        return functools.reduce(operator.xor, coord, 0)

此方法与使用map生成coord是一样的

这里:

1.。使用了操作符函数代替了异或符号, operator.xor

2. reduce返回一个聚合值,并且reduce的默认值——第三个参数最好设置

同时到了这一步,我们会发现我们之前的__eq__有点不太好了,因为它需要复制一份元组,效率比较低,

当数据增大时,我们需要更快地方法。这思路有点像生成器的原理。

    def __eq__(self, other):
        return len(self) == len(other) and all(a == b for a, b in zip(self, other))

以上这句挺有味道,因为它先比较长度,避免zip终止过早。同时使用了all,all函数接受一个可迭代对象并且返回一个布尔值,这个可迭代对象中的迭代值一定得是bool(根据这代码瞎猜的)。




猜你喜欢

转载自blog.csdn.net/weixin_41958153/article/details/80661154
今日推荐