python中关于拆包的疑问?

新手上路,请多包涵
class Vector2d:
    typecode = 'd'

    def __init__(self, x, y):
        self.x = float(x)
        self.y = float(y)

    def __iter__(self):
        return (i for i in (self.x, self.y))

    def __repr__(self):
        class_name = type(self).__name__
        return '{}({!r}, {!r})'.format(class_name, *self)    #(1)

    def __str__(self):
        return str(tuple(self))

    def __bytes__(self):
        return (bytes([ord(self.typecode)]) +
                bytes(array(self.typecode, self)))

    def __eq__(self, other):
        return tuple(self) == tuple(other)

    def __abs__(self):
        return math.hypot(self.x, self.y)

    def __bool__(self):
        return bool(abs(self))

我在读《流畅的python》,上面代码(1)处的self,我不明白这里为什么要加号,这个类实现了__iter__,可以迭代,拆包,直接写self不就可以把self.x,self.y传后两个{!r}里了吗?在我的理解中,只有定义不定参数的函数形参中会用到*,还有就是平行赋值,比如:

>>> a, b, *rest = range(5)
>>> a, b, rest
(0, 1, [2, 3, 4])
阅读 1.5k
2 个回答

这个类的确实现了迭代协议,不过需要在加*后触发__iter__这个方法

format函数本来需要3个参数:

'{}({!r}, {!r})'.format(a, b, c)

如果你直接将self传进去,self是作为一个整体进行传递,这样format还需要第三个参数:

'{}({!r}, {!r})'.format(class_name, self)

如果你在self前面加上星号,表示将self进行拆包后再进行传递,等价于:

'{}({!r}, {!r})'.format(class_name, self.x, self.y)

这是两种不同的语义:①将对象做为整体传递;②将可迭代对象拆包逐个传递。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题