简体   繁体   English

如何使用__add__方法在python中添加稀疏向量

[英]How to use __add__ method to add sparse vectors in python

I am given an assignment to add two sparse vectors using special methods in SparseVec(length) class.I have limited understanding of special methods and method overloading, can you please describe what i am missing in the following code and what exactly is method overloading?我被赋予了使用 SparseVec(length) 类中的特殊方法添加两个稀疏向量的任务。我对特殊方法和方法重载的理解有限,您能否描述一下我在以下代码中缺少的内容以及方法重载究竟是什么? I have two alternatives: using stand alone functions and class methods(OOP).我有两种选择:使用独立函数和类方法(OOP)。 I want to know the advantage of the later (OOP).我想知道后者的优势(OOP)。

Stand-alone function (Works fine)独立功能(工作正常)

def SparseVec(numbers):
    dic={}
    for key,val in enumerate(numbers):
        if val:
            dic[key]=val
    return dic

numbers=[-1,0,9.2,0]
a=SparseVec(numbers)
print(a)

numbers2=[0,1,0,0,0]
b=SparseVec(numbers2)
print(b)

#Adds and merges values with keys in two dictionaries
def merged_dictionaries(a,b):
    merged_dict={}
    for key in a:
        if key in b:
            new_value=a[key]+b[key]
        else:
            new_value=a[key]
        merged_dict[key]=new_value
    for key in b:
        if key not in merged_dict:
            merged_dict[key]=b[key]
    return merged_dict
c=merged_dictionaries(a,b)
for key, val in c.items(): # SparseVec iterator
    print ('c[%d]=%g ' % (key,val))
print(c)

class method(OOP)-(Defective)类方法(OOP)-(有缺陷)

#Implements a Sparse vector (vector with many zero values) and adds two sparse vectors
class SparseVec:
    #initializes the instance with given length
    def __init__(self,length):
        self.length=length
        self.data={}
    def __str__(self):
        return 'Dense Vector {}'. format(self.data)
    #Returns the length of the vector
    def __len__(self):
        return len(self.data)
    # Returns nonzeros from the given(self) dictionary
    def __getitem__(self, item):
        return self.data
    def __setitem__(self, key, val):
        #To set a value by its key
        self.data[key]= val

    def nonzeros(self):
        nonzerodict = {}
        for key, val in enumerate(self):
            if val:
                nonzerodict[key] = val
        return nonzerodict
    def __add__(self, other):
        c = {}
        for key in self:
            if key in other:
                new_value = self[key]+ other[key]
            else:
                new_value = self[key]
            c[key] = new_value
        for key in other:
            if key not in c:
                c[key] = other[key]
        return c

a = SparseVec(4)
a[2] = 9.2
a[0] = -1
print(a)
print(a.nonzeros())
b = SparseVec(5)
b[1] = 1
print(b.nonzeros())
c=a+b
print(c)

You need to add the components of each vector pairwise, and return a SparseVector object:您需要成对添加每个向量的分量,并返回一个SparseVector对象:

class SparseVec:

    def __init__(self, dimension):
        self.dimension = dimension
        self.data = {}

    def __str__(self):
        return 'Sparse Vector {}'. format(self.data)

    def __len__(self):
        return self.dimension    # what matters is the size of the vector, not the length of the stored data

    def __getitem__(self, key):
        assert isinstance(key, int)
        assert 0 <= key < self.dimension, 'the key must be compatible with the vector dimension' 
        try:
            return self.data[key]
        except KeyError:
            return 0     # must return zero if valid key but no entry

    def __setitem__(self, key, val):
        assert isinstance(key, int)
        assert 0 <= key < self.dimension, 'this vector does not have an appropriate dimension'
        if val != 0:     # avoid cluttering with zero values
            self.data[key] = val

    def purge_zeros(self):  # <-- resparsifies a vector by purging the zero values
        nonzerodict = {}
        for key, val in self.data.items():
            if val != 0:
                nonzerodict[key] = val
        self.data = nonzerodict

    def __add__(self, other):
        assert self.dimension == other.dimension, 'vectors must have the same dimension'
        resulting_vector = SparseVec(self.dimension)
        c = {k:v for k, v in self.data.items()}  # <-- copies self data
        for k, v in other.data.items():
            try:
                c[k] += v
            except KeyError:
                c[k] = v
        resulting_vector.data = c
        resulting_vector.purge_zeros()
        return resulting_vector

tests:测试:

a = SparseVec(4)
b = SparseVec(4)
a.data = {0: 2, 1: 1}
b.data = {0: -2, 1: 2, 2: 4}
print(a + b)
print(a[0], a[1], a[2], a[3])
print(b[0], b[1], b[2], b[3])
a[3] = -3
print(a[0], a[1], a[2], a[3])

output:输出:

Sparse Vector {1: 3, 2: 4}
2 1 0 0
-2 2 4 0
2 1 0 -3

Overloading a class method is essentially writing a method that would usually be handled by a default method in Python and replacing it with your own method for that class.重载类方法本质上是编写一个通常由 Python 中的默认方法处理的方法,并将其替换为该类的您自己的方法。

This is the default add method from Python 3 docs: https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types这是 Python 3 文档中的默认添加方法: https : //docs.python.org/3/reference/datamodel.html#emulating-numeric-types

I'm not sure on why you are using a dict for this rather than a list without more context, but the following should work:我不确定您为什么为此使用 dict 而不是没有更多上下文的列表,但以下应该有效:

c = a.add(b)
print(c)

a is an instance of the SparseVec class, so in order to access the add method we call a.add() and pass in the other object we wish to add to it. a 是 SparseVec 类的一个实例,因此为了访问add方法,我们调用 a.add() 并传入我们希望添加到它的另一个对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM