在Python中使用字符串还是枚举检查对象类型

1 投票
4 回答
1352 浏览
提问于 2025-04-17 03:08

假设我有一个叫做 Tag 的对象,并且我有三种类型的标签,这些类型通过一个实例变量来表示,具体如下:

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

还是说我应该创建一个类似枚举的对象,就像这个问题里提到的那样,

class Type:
    COLD=1
    WARM=2        
    HOT=3

然后像这样创建标签呢?

t1 = Tag("blue", Type.COLD)

我之所以问这个问题,是因为我听说比较字符串会消耗很多处理能力。虽然这些标签只有三到四个字母,但我可能会进行成千上万次这样的比较。你觉得为了判断一个对象的类型,创建枚举对象值得吗?还是说有更好的方法来实现我想做的事情呢?

4 个回答

2

我觉得不用太担心这个性能问题,除非通过性能分析发现确实有问题。如果你在使用集成开发环境(IDE),那么使用枚举的方式还有一个好处,就是可以检查拼写错误。

2

性能差异可能并没有那么大,值得你去担心。如果你对性能有疑虑,可以做个简单的测试。可以使用Python的 timeit 模块来测试这两种情况的性能。

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   

撰写回答