2011-09-26 95 views
1
检查对象的类型

说我有一个名为标签的对象,我有三个类型的标签通过以下方式实例变量指出,字符串与枚举在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信长的话,很可能我会做几数以千计的这些类型的比较。你认为它值得去创建枚举对象来确定一个对象的类型,就像我在上面显示的例子那样?还是有更好的方法来做我想做的事情?

+2

我认为您列举的解决方案的一个优点是它明确了允许的值是什么。如果你接受任意字符串,我会认为'更容易犯错误,更难记录你的词汇。例如,'logging'模块使用这种解决方案来记录日志级别(例如'logging.DEBUG','logging.INFO'等等)。 – larsks

回答

0

在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 
2

性能差异可能不足以让您担心。如果你关心性能,你应该做一个简单的测试。使用Python的timeit模块来测试这两种情况的性能。

2

我不会担心这种表现,除非分析表明它确实是一个问题。如果您使用的是IDE,则枚举方法具有错字检查功能。

+0

是的---错字检查和指定允许的值在这里很重要,可能不是性能。 – JasonFruit

1

我会去相结合的方式 - 有“枚举”是部分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()