У меня возникли проблемы с добавлением двух объектов класса вместе. Это код, предоставленный мне, который будет запускать MY файл, HyperLogLog и образец текстового файла:
import HyperLogLog
import sys
hlls = [HyperLogLog.HyperLogLog() for _ in range(5)]
with open(sys.argv[1], "r") as file:
for line in file:
cleanLine = line.replace("\n", "")
(cmd, set, value) = cleanLine.split(" ")[:3]
# See if this was an add, count, or merge command
if cmd == "A":
hlls[int(set)].add(value)
elif cmd == "C":
estimate = hlls[int(set)].count()
print("Estimate:", estimate, "Real count:", value)
elif cmd == "M":
(cmd, m1, m2, m3) = cleanLine.split(" ")
hlls[int(m3)] = hlls[int(m1)] + hlls[int(m2)]
Самая нижняя строка - объединение hlls (set m1) и hlls (set m2). hlls (set x) хранит единственный параметр M, который является моим вектором HyperLogLog. Мне нужно сделать функцию добавления, чтобы сделать линию добавления выше работы. Это я сделал следующим образом:
class HyperLogLog:
def __init__(self):
self.M = [0 for x in range(m)]
##############
Code altering the self.M
##############
def __add__(self, other):
Sum=other.M
for i,value in enumerate(other.M):
if value<self.M[i]:
Sum[i]=self.M[i]
self.M=Sum
return self
Это вернет правильное значение для набора m3. Но это также изменит значение self.M set m1. Как я могу вернуть что-то другое, кроме себя, которое сделает hlls [int (m3)] и экземпляр класса HyperLogLog, с объединенным значением self.M?
Если я просто верну функцию Sum, hlls [int (m3)] больше не является экземпляром класса HyperLogLog.
Если я изменяю self.M, как и я, я изменяю значение self.M для hlls [int (m1)].
Если я сделаю что-то вроде:
def __add__(self, other):
Sum=other.M
for i,value in enumerate(other.M):
if value<self.M[i]:
Sum[i]=self.M[i]
self2=self
self2.M=Sum
return self2
Значение self.M экземпляра hlls [int (m1)] по-прежнему изменяется. Я не понимаю, почему.
Это не создает новый экземпляр объекта. Он просто назначает другое имя тому же самому объекту.
self2=self
Вы должны создать новый объект HyperLogLog
в методе __add__
. Что-то вроде этого:
def __add__(self, other):
retval = HyperLogLog()
retval.M = [max(a, b) for a, b in zip(self.M, other.M)]
return retval
Когда вы это сделаете:
self2=self
И self
и self2
указывают на один и тот же объект, поэтому, когда один изменяется, меняется и другой. Самым простым HyperLogLog
было бы создать новый объект HyperLogLog
, поэтому вы заменили бы строку выше:
self2=HyperLogLog()