【问题标题】:Python-like operator overloading in SwiftSwift 中类似 Python 的运算符重载
【发布时间】:2015-02-02 17:06:43
【问题描述】:

我开始使用 Swift。我以前的编程背景主要是 Python,所以我倾向于在 Swift 中搜索 Pythonic 的编码方式,幸运的是它部分受到了 Python 的启发。在 Python 中,有一种非常强大的方法可以通过使用特殊方法来重载类中的运算符。我知道我们可以通过在特定名称空间中定义一个函数来重载 Swift 中的运算符,我们想要这种特殊行为,但我还没有找到一种方法来按类重载运算符。

编辑 - 添加示例。

class Vector(object):
    def __init__(self, *args):  # Initializing a vector of random size
        self.vector = tuple(args)

    def __len__(self):  # This sources the data to the built-in len() function
        return len(self.vector)

    def __getitem__(self, i):  # Overloads [ ] operator
        return self.vector[i]

    def __add__(self, vector):  # Overloads + operator
        if len(self) != len(vector):
            raise ValueError("Vectors should be of equal length")
        return tuple([self.vector[i] + vector[i] for i in xrange(len(self))])


a, b = Vector(1, 2, 3, 4), Vector(2, 3, 4, 5)  # My modified tuples

print(a + b)  # this operation is affected
print((1, 2, 3, 4) + (2, 3, 4, 5))  # this is not, since these are standard tuples

输出:

(3, 5, 7, 9) 
(1, 2, 3, 4, 2, 3, 4, 5)

在这里,我刚刚通过定义 add 方法重载了 +,并通过定义 getitem 方法重载了 []。该类可以从 Python 中的元组类型以及初始化程序中继承 [] 行为,但我手动进行了所有操作以提供更多详细信息。由于重载被封装在类中,它不会影响一般的运算符行为,因为所有类型和类都定义了自己的特殊方法。

【问题讨论】:

  • 所以也许你会悄悄告诉 Swift 专家,它是如何在 Python 中完成的。
  • 一般来说,Swift 中的运算符重载总是全局的。您可以做的最接近的方法是创建特定于类型的运算符重载。此外,正如 Thomas 所说,如果您提供所有相关信息,您更有可能得到有用的答案。
  • @ThomasKilian 我刚刚添加了一个示例。
  • @David 现在有一个例子。

标签: python swift operator-overloading


【解决方案1】:

使用不同机制覆盖的几个不同的运算符。 __getitem__ 的等价物是覆盖 subscript 要覆盖 plus,您需要在全局空间中实现 func +,最终得到:

class Vector<T> {
    let vector : [T]

    init(values:[T]) {
        vector = values
    }

    subscript(index:Int) -> T {
        get {
            return vector[index]
        }
    }

    func len() -> Int {
        return vector.count
    }
}

protocol Addable {
    func +(lhs:Self, rhs:Self) -> Self
}

func + <T:Addable>(left:Vector<T>, right:Vector<T>) -> Vector<T> {
    var result = [T]()

    assert(left.len() == right.len(), "vectors should be of equal length")
    for i in 0 ..< left.len() {
        result.append( left[i] + right[i] )
    }

    return Vector(values: result)
}

请注意,我已将其实现为泛型,因此分散在各处。您还需要指出您使用的任何数据类型都实现了 Addable 协议。这很简单:

extension Int : Addable {}

我还可能会指出,Vector 类并没有真正通过标准数组类和重写运算符获得的好处,如下所示:

func + <T:Addable>(left:Array<T>, right:Array<T>) -> Array<T> {
    var result = [T]()

    assert(left.len() == right.len(), "vectors should be of equal length")
    for i in 0 ..< left.len() {
        result.append( left[i] + right[i] )
    }

    return result
}

在任何一种情况下,您都可以使用内联 + 运算符轻松地对数组或向量执行向量数学运算。

【讨论】:

  • Vector 类,也就是向量化求和运算,只是我想到的第一个例子。所以,如果我做对了,只要所有重载函数都具有不同的类型推断,我就可以在一段代码中多次重载同一个运算符?
  • 是的。运算符重载遵循 swift 函数重载的所有常规规则,因此它们必须在参数计数和/或类型或结果类型方面有所不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多