基本上,我有一个列表:[START, 'foo', 'bar', 'spam', eggs', END]
,后面需要START / END标识符,以便稍后进行比较。现在,我把它设置成这样:
START = object()
END = object()
这很好用,但是它遇到了不能使用酸洗的问题。我试着按照以下方式做到这一点,但这似乎是一种实现这个目标的可怕方法:
class START(object):pass
class END(object):pass
有人可以分享更好的方法吗?另外,我上面设置的例子只是对另一个问题的过度简化。
答案 0 :(得分:10)
如果你想要一个保证唯一的对象和也可以保证恢复到完全相同的标识,如果是右后卫,顶层函数,类,类实例,如果你关心is
而不是==
也列出(以及其他可变项),那么一切都很好。即,任何一个:
# work for == as well as is
class START(object): pass
def START(): pass
class Whatever(object): pass
START = Whatever()
# if you don't care for "accidental" == and only check with `is`
START = []
START = {}
START = set()
这些都不可怕,没有任何特殊优势(取决于您是否关注==
或is
)。可能def
通过普遍性,简洁性和较轻的权重获胜。
答案 1 :(得分:2)
您可以定义一个Symbol
类来处理START和END。
class Symbol:
def __init__(self, value):
self.value = value
def __eq__(self, other):
return isinstance(other, Symbol) and other.value == self.value
def __repr__(self):
return "<sym: %r>" % self.value
def __str__(self):
return str(self.value)
START = Symbol("START")
END = Symbol("END")
# test pickle
import pickle
assert START == pickle.loads(pickle.dumps(START))
assert END == pickle.loads(pickle.dumps(END))
答案 2 :(得分:1)
如果你的列表没有字符串,我只使用“start”,“end”,因为Python因为实习而进行比较O(1)。
如果你确实需要字符串,而不是元组,那么完整的cheapskate方法是:
[("START",), 'foo', 'bar', 'spam', eggs', ("END",)]
PS:我确定你的名单是之前的数字,而不是字符串,但我看不到任何修改,所以我一定想象它
答案 3 :(得分:1)
实际上,我喜欢你的解决方案。
前段时间我正在攻击Python模块,我希望有一个特殊的魔法值,这在其他任何地方都无法出现。我花了一些时间思考它,我提出的最好的是你使用的相同技巧:声明一个类,并使用类对象作为特殊的魔法值。
当您检查哨兵时,您当然应该使用is
运算符来识别对象:
for x in my_list:
if x is START:
# handle start of list
elif x is END:
# handle end of list
else:
# handle item from list
答案 4 :(得分:0)
我想如果你更明确地知道你需要什么,这可能会更容易回答,但是如果面对像这样的问题我会倾向于:
>>> START = os.urandom(16).encode('hex')
>>> END = os.urandom(16).encode('hex')
这种方法的优点,正如我所看到的那样
object()
或空类的情况。缺点(?)