#python
#python
Вопрос:
У меня есть набор кортежей, каждый из которых имеет три значения данных. Проблема, над которой я работаю, требует от меня кодирования четырех значений данных в каждом кортеже, но четвертое значение не должно учитываться при определении эквивалентности кортежей. Более формально,
tuple1 = ('a', 'b', 'c', 'd')
tuple2 = ('a', 'b', 'c', 'f')
tuple1 == tuple2 # Should be true
Кроме того, если tuple1
было в наборе, tuple2
не может быть добавлено к этому набору
Каков наилучший способ реализовать это «скрытое» значение таким образом, чтобы это не повлияло на эквивалентность кортежей?
Я рассматривал возможность создания класса, который заключает в себе кортеж, и переопределения функций equal () и hash (), так что последний элемент не имеет значения в этом аспекте. Однако проблема, над которой я работаю, требует больших вычислительных затрат, и поэтому мне было интересно, есть ли более быстрые способы реализации этой функциональности.
Если вы знаете о каких-либо, пожалуйста, поделитесь. Спасибо.
Комментарии:
1. Насколько мне известно, встроенной функциональности нет.
2. Учитывая ваше требование размещать элементы в наборах, я думаю, вам придется написать свой собственный класс. Мне также любопытно посмотреть, есть ли другие способы, которыми это можно сделать.
3. Вы могли бы попробовать создать подкласс
tuple
, при этом ваше дополнительное значение будет помещено в слот экземпляра, а не в сам кортеж.4. Что вы хотите получить на выходе
{tuple1} | {tuple2}
? Должно ли это вызывать ошибку, и если нет, то какой кортеж «выигрывает»?5. Что ж, если вы помещаете их в dicts, вам все равно придется решать эту проблему! (наборы — это просто dicts с нулевыми значениями)
Ответ №1:
Вы можете создать подкласс tuple
и __new__
, используя комбинацию __init__
и,, создать кортеж, который также содержит 4-й атрибут в качестве отдельного атрибута. Я не знаю, насколько «похожим на кортеж» должно быть ваше решение, но это простое решение.
class MyTuple(tuple):
def __new__(cls, a, b, c, d):
return super(MyTuple, cls).__new__(cls, (a,b,c))
def __init__(self, a, b, c, d):
self.d = d
@property
def as_tuple(self):
return self (self.d,)
def __repr__(self):
return 'Mytuple' repr(self.as_tuple)
def __str__(self):
return str(self.as_tuple)
tuple1 = MyTuple('a', 'b', 'c', 'd')
tuple2 = MyTuple('a', 'b', 'c', 'f')
tuple3 = MyTuple('w', 'x', 'y', 'z')
my_dict = {tuple1:'one', tuple2:'two', tuple3:'three'}
print('hashed', my_dict)
Комментарии:
1. Я не нахожу идею убедительной. Преобразование неизменяемого типа в изменяемый кажется сложным. Кроме того, мы теперь переносим
__dict__
на каждый экземпляр… хммм2. Обычно помещение
__slots__ = ['d']
в класс позволило бы избежать создания этого dict в каждом экземпляре — но, к сожалению, это не работает с кортежами (из-за их природы переменного размера).3. @wim — наследование неизменяемого типа, возможно, не распространено, но, безусловно, имеет свое применение, и я не нахожу эту часть беспокоящей. Дополнительное пространство и дополнительное время, необходимые для создания экземпляра объекта, могут стать препятствием для сделки, но на современном оборудовании это должен быть значительный набор данных, прежде чем я буду беспокоиться. Есть много способов, которыми python может сжечь ваше ядро и съесть вашу оперативную память!
4. @jasonharper да, я был немного удивлен, когда
TypeError: nonempty __slots__ not supported for subtype of 'tuple'
появился в моей первой попытке.5. Я не ограничен использованием кортежей. Пока структура данных является хэшируемой, все хорошо. Весь смысл в том, что я могу использовать tuple / MyTuple как отдельный ключ к хэш-таблице. Если tuple1 является ключом в словаре, то Dict[tuple2] должен возвращать то же значение, что и Dict[tuple1] .
Ответ №2:
Вместо того, чтобы думать о вашей проблеме как о наборе кортежей (каждый со скрытым значением), не могли бы вы представить это как сопоставление словаря заданному кортежу со скрытым значением?