我喜欢使用表达
if 'MICHAEL89' in USERNAMES:
...
USERNAMES
清单在哪里。
有什么方法可以区分大小写不敏感的项目,还是需要使用自定义方法?只是想知道是否需要为此编写额外的代码。
我喜欢使用表达
if 'MICHAEL89' in USERNAMES:
...
USERNAMES
清单在哪里。
有什么方法可以区分大小写不敏感的项目,还是需要使用自定义方法?只是想知道是否需要为此编写额外的代码。
Answers:
username = 'MICHAEL89'
if username.upper() in (name.upper() for name in USERNAMES):
...
或者:
if username.upper() in map(str.upper, USERNAMES):
...
或者,可以的,您可以定制方法。
[...]
创建整个列表。(name.upper() for name in USERNAMES)
一次只能创建一个生成器和一个所需的字符串-如果您经常执行此操作,则可以节省大量内存。(如果您只是创建一个小写的用户名列表,然后每次都重复使用以进行检查,则可以节省更多费用)
我会做一个包装纸,这样您就可以做到无创。至少,例如:
class CaseInsensitively(object):
def __init__(self, s):
self.__s = s.lower()
def __hash__(self):
return hash(self.__s)
def __eq__(self, other):
# ensure proper comparison between instances of this class
try:
other = other.__s
except (TypeError, AttributeError):
try:
other = other.lower()
except:
pass
return self.__s == other
现在,if CaseInsensitively('MICHAEL89') in whatever:
应按要求运行(无论右侧是列表,字典还是集合)。(可能需要付出更多的努力才能获得相似的字符串包含结果,在某些情况下避免发出警告,包括unicode
等等)。
CaseInsensitively('MICHAEL89') in {CaseInsensitively('Michael89'):True}
使其正常工作,而这可能不属于“按要求进行”。
etc.
是我的回答的简短和“需要更多的努力”部分;-)。
通常(至少在oop中),您可以对对象进行形状调整,使其表现出所需的效果。name in USERNAMES
不区分大小写,因此USERNAMES
需要更改:
class NameList(object):
def __init__(self, names):
self.names = names
def __contains__(self, name): # implements `in`
return name.lower() in (n.lower() for n in self.names)
def add(self, name):
self.names.append(name)
# now this works
usernames = NameList(USERNAMES)
print someone in usernames
这样做的好处在于,它无需进行任何类外的代码更改,便可以进行许多改进。例如,您可以将更self.names
改为一组以进行更快的查找,或者(n.lower() for n in self.names)
仅计算一次并将其存储在类中,依此类推...
str.casefold
建议使用不区分大小写的字符串匹配。@nmichaels的解决方案可以轻松调整。
使用以下任一方法:
if 'MICHAEL89'.casefold() in (name.casefold() for name in USERNAMES):
要么:
if 'MICHAEL89'.casefold() in map(str.casefold, USERNAMES):
根据文档:
大小写折叠类似于小写字母,但是更具攻击性,因为它旨在消除字符串中的所有大小写区别。例如,德语小写字母“ß”等效于“ ss”。由于它已经是小写字母,
lower()
因此对“ß”无效。casefold()
将其转换为“ ss”。
你可以做
matcher = re.compile('MICHAEL89', re.IGNORECASE)
filter(matcher.match, USERNAMES)
更新:玩了一会儿,我认为您可以使用以下方法获得更好的短路类型方法
matcher = re.compile('MICHAEL89', re.IGNORECASE)
if any( ifilter( matcher.match, USERNAMES ) ):
#your code here
该ifilter
函数来自itertools,它是Python中我最喜欢的模块之一。它比生成器快,但仅在被调用时才创建列表的下一项。
我需要此字典而不是列表,Jochen解决方案在这种情况下是最优雅的,因此我对其进行了修改:
class CaseInsensitiveDict(dict):
''' requests special dicts are case insensitive when using the in operator,
this implements a similar behaviour'''
def __contains__(self, name): # implements `in`
return name.casefold() in (n.casefold() for n in self.keys())
现在您可以像这样转换字典USERNAMESDICT = CaseInsensitiveDict(USERNAMESDICT)
并使用if 'MICHAEL89' in USERNAMESDICT:
if 'CaseFudge'.lower() in [x.lower() for x in list]