Мне нужно выполнить сравнения строк без учета регистра в python в наборах и словарных клавишах. Теперь для создания наборов и подклассов dict, которые нечувствительны к регистру, оказывается удивительно сложным (см.: Нечувствительный к регистру словарь для идей, обратите внимание, что все они используют ниже - эй там даже отклоненный PEP, хотя его объем немного шире). Поэтому я пошел с созданием нечувствительного к регистру строкового класса (используя этот ответ by @AlexMartelli):
class CIstr(unicode):
"""Case insensitive with respect to hashes and comparisons string class"""
#--Hash/Compare
def __hash__(self):
return hash(self.lower())
def __eq__(self, other):
if isinstance(other, basestring):
return self.lower() == other.lower()
return NotImplemented
def __ne__(self, other): return not (self == other)
def __lt__(self, other):
if isinstance(other, basestring):
return self.lower() < other.lower()
return NotImplemented
def __ge__(self, other): return not (self < other)
def __gt__(self, other):
if isinstance(other, basestring):
return self.lower() > other.lower()
return NotImplemented
def __le__(self, other): return not (self > other)
Я полностью понимаю, что lower
не очень-то достаточно, чтобы охватить все случаи сравнения строк в юникоде, но я рефакторинг существующего кода, который использовал много clunkier-класс для сравнения строк (память и скорость), которые в любом случае использовали lower() - поэтому я могу изменить это на более позднем этапе - плюс я на python 2 (как видно на unicode
). Мои вопросы:
-
Я получил операторы правильно?
-
- этот класс достаточно для моих целей, учитывая, что я позабочусь о создании ключей в dicts и наборе элементов как экземпляры
CIstr
- мои цели - проверка равенства, сдерживания, установки различий и аналогичных операций в нечувствительном к регистру путь. Или я что-то упускаю? -
Стоит ли кэшировать строчную версию строки (как видно, например, в этом древнем рецепте python: Нечувствительные к регистру строки). Этот comment предполагает, что нет - плюс я хочу построить как можно быстрее и размер как можно меньше, но люди, похоже, включают это.
Советы по совместимости с Python 3 оценены!
Маленькая демонстрация:
d = {CIstr('A'): 1, CIstr('B'): 2}
print 'a' in d # True
s = set(d)
print {'a'} - s # set([])