python 中的不区分大小写的字符串 class
A case insensitive string class in python
我需要在 python 中的集合和字典键中执行不区分大小写的字符串比较。现在,要创建不区分大小写的集合和 dict subclasses 证明非常棘手(请参阅:@AlexMartelli 的 Case insensitive dictionary for ideas, note they all use lower - hey there's even a rejected PEP, albeit its scope is a bit broader). So I went with creating a case insensitive string class (leveraging this answer):
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
是 not really enough 以涵盖 unicode 中字符串比较的所有情况,但我正在重构现有代码,这些代码使用更笨重的 class 进行字符串比较(内存和速度方面)无论如何使用 lower() - 所以我可以在稍后阶段修改它 - 而且我在 python 2(如 unicode
所见)。我的问题是:
我的运算符正确吗?
这个 class 是否足以满足我的目的,因为我注意在字典中构造键并将元素设置为 CIstr
实例 - 我的目的是检查相等性、包容性,以不区分大小写的方式设置差异和类似操作。还是我遗漏了什么?
是否值得缓存字符串的小写版本(例如在这个古老的 python 食谱中看到的:Case Insensitive Strings). This comment 建议不这样做 - 而且我想要尽可能快地建造,尽可能小,但人们似乎包括这个。
Python 感谢 3 个兼容性提示!
小型演示:
d = {CIstr('A'): 1, CIstr('B'): 2}
print 'a' in d # True
s = set(d)
print {'a'} - s # set([])
大部分代码看起来都不错。我会删除 __ge__
、__le__
和 __ne__
中的快捷方式,并将它们扩展为直接调用 lower()。
这个快捷方式看起来像在`functools.total_ordering() 中所做的,但它只会减慢代码速度并使测试跨类型比较变得更加困难当方法相互依赖时,很难做到正确。
在您的演示中,您正在使用 'a'
在您的集合中查找内容。如果您尝试使用 'A'
,它将不起作用,因为 'A'
具有不同的哈希值。 'A' in d.keys()
也为真,但 'A' in d
为假。通过声称等于具有不同哈希值的对象,您实际上已经创建了一种违反所有哈希值的正常契约的类型。
您可以将此答案与有关创建专用字典的答案结合起来,并在尝试查找之前将任何可能的键转换为 CIstr
的字典。那么你所有的 CIstr
转换都可以隐藏在字典 class.
中
例如
class CaseInsensitiveDict(dict):
def __setitem__(self, key, value):
super(CaseInsensitiveDict, self).__setitem__(convert_to_cistr(key), value)
def __getitem__(self, key):
return super(CaseInsensitiveDict, self).__getitem__(convert_to_cistr(key))
# __init__, __contains__ etc.
(基于)
我需要在 python 中的集合和字典键中执行不区分大小写的字符串比较。现在,要创建不区分大小写的集合和 dict subclasses 证明非常棘手(请参阅:@AlexMartelli 的 Case insensitive dictionary for ideas, note they all use lower - hey there's even a rejected PEP, albeit its scope is a bit broader). So I went with creating a case insensitive string class (leveraging this answer):
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
是 not really enough 以涵盖 unicode 中字符串比较的所有情况,但我正在重构现有代码,这些代码使用更笨重的 class 进行字符串比较(内存和速度方面)无论如何使用 lower() - 所以我可以在稍后阶段修改它 - 而且我在 python 2(如 unicode
所见)。我的问题是:
我的运算符正确吗?
这个 class 是否足以满足我的目的,因为我注意在字典中构造键并将元素设置为
CIstr
实例 - 我的目的是检查相等性、包容性,以不区分大小写的方式设置差异和类似操作。还是我遗漏了什么?是否值得缓存字符串的小写版本(例如在这个古老的 python 食谱中看到的:Case Insensitive Strings). This comment 建议不这样做 - 而且我想要尽可能快地建造,尽可能小,但人们似乎包括这个。
Python 感谢 3 个兼容性提示!
小型演示:
d = {CIstr('A'): 1, CIstr('B'): 2}
print 'a' in d # True
s = set(d)
print {'a'} - s # set([])
大部分代码看起来都不错。我会删除 __ge__
、__le__
和 __ne__
中的快捷方式,并将它们扩展为直接调用 lower()。
这个快捷方式看起来像在`functools.total_ordering() 中所做的,但它只会减慢代码速度并使测试跨类型比较变得更加困难当方法相互依赖时,很难做到正确。
在您的演示中,您正在使用 'a'
在您的集合中查找内容。如果您尝试使用 'A'
,它将不起作用,因为 'A'
具有不同的哈希值。 'A' in d.keys()
也为真,但 'A' in d
为假。通过声称等于具有不同哈希值的对象,您实际上已经创建了一种违反所有哈希值的正常契约的类型。
您可以将此答案与有关创建专用字典的答案结合起来,并在尝试查找之前将任何可能的键转换为 CIstr
的字典。那么你所有的 CIstr
转换都可以隐藏在字典 class.
例如
class CaseInsensitiveDict(dict):
def __setitem__(self, key, value):
super(CaseInsensitiveDict, self).__setitem__(convert_to_cistr(key), value)
def __getitem__(self, key):
return super(CaseInsensitiveDict, self).__getitem__(convert_to_cistr(key))
# __init__, __contains__ etc.
(基于)