字符串与枚举在Python中
问题描述:
检查对象的类型
说我有一个名为标签的对象,我有三个类型的标签通过以下方式实例变量指出,字符串与枚举在Python中
class Tag(object):
def __init__(self, name, type):
self.name = name
self.type = type
t1 = Tag("blue", "cold")
t2 = Tag("red", "warm")
t3 = Tag("black", "hot")
比方说,我只允许三种类型:冷,热和热。最好去检查它是否是这种类型之一?
if t1.type == "cold":
# do something
elif t1.type == "warm":
# do something else
else t1.type == "hot":
# do something even elser
或者我应该创建一个枚举类的物体,像从这个question之一,
class Type:
COLD=1
WARM=2
HOT=3
,而是创建这样的标签?
t1 = Tag("blue", Type.COLD)
我之所以问这个问题,是因为我听到了很多的处理能力,进入比较字符串,即使这些短短的3,4信长的话,很可能我会做几数以千计的这些类型的比较。你认为它值得去创建枚举对象来确定一个对象的类型,就像我在上面显示的例子那样?还是有更好的方法来做我想做的事情?
答
在python中,使用字典进行调度比使用if/elif/else的塔更经常是有利的。
所以:
class Tag(object):
def __init__(self, name, type):
self.name = name
self.type = type
self.dispatch = {"cold":Tag.process_cold, "warm":Tag.process_warm, "hot":Tag.process_hot}
def process(self):
self.dispatch[type](self)
def process_cold(self):
# do something
def process_warm(self):
# do something else
def process_hot(self):
# do something even elser
和代码一小笔额外位可以自动建立调度表:
def dispatchTable(klass, prefix):
"""
Given a class and a method prefix string, collect all methods in the class
that start with the prefix, and return a dict mapping from the part of the
method name after the prefix to the method itself.
e.g. you have a class Machine with methods opcode_foo, opcode_bar.
create_dispatch_table(Machine, "opcode_")
yields a dict
{ "foo": Machine.opcode_foo, "bar": Machine.opcode_bar }
"""
dispatch = {}
for name, fun in inspect.getmembers(klass, inspect.ismethod):
if name.startswith(prefix):
# print "found %s.%s"%(k.__name__,name)
dispatch[ name.split(prefix)[1] ] = fun
return dispatch
答
我会去相结合的方式 - 有“枚举”是部分Tag类的接受一个字符串进行初始化,然后将其转换。另外,不要使用一堆if/else分支,你可以使用一个字典来创建一个分派表。
class Tag(object):
COLD = 0
WARM = 1
HOT = 2
def __init__(self, name, temp):
if temp.upper() not in ('COLD', 'WARM', 'HOT'):
raise ValueError("Invalid temp: %r" % temp)
self.temp = getattr(self, temp.upper())
self.name = name
def process(self):
func = self.temp_dispatch[self.temp]
func(self) # NOTE: have to pass 'self' explicitly
def cold(self):
print('brrr')
def warm(self):
print('ahhh')
def hot(self):
print('ouch!')
temp_dispatch = {COLD:cold, WARM:warm, HOT:hot}
tag = Tag('testing', 'Cold')
tag.process()
我认为您列举的解决方案的一个优点是它明确了允许的值是什么。如果你接受任意字符串,我会认为'更容易犯错误,更难记录你的词汇。例如,'logging'模块使用这种解决方案来记录日志级别(例如'logging.DEBUG','logging.INFO'等等)。 – larsks