用于检查Python中对象类型的字符串与枚举

用于检查Python中对象类型的字符串与枚举,python,string,performance,types,enums,Python,String,Performance,Types,Enums,假设我有一个名为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") 假设我只允许三种类型:冷、热和热。是否最好去检查一下它是

假设我有一个名为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
t1 = Tag("blue", Type.COLD)
或者我应该创建一个类似枚举的对象

而是像这样创建标签

if t1.type == "cold":
    # do something
elif t1.type == "warm":
    # do something else
else t1.type == "hot":
    # do something even elser
t1 = Tag("blue", Type.COLD)

我问这个问题的原因是因为我听说比较字符串需要很大的处理能力,即使这些是3个或4个字母长的短单词,我也可能会对这些类型进行成千上万次的比较。您认为创建枚举对象来确定对象的类型是否值得,如我上面所示的示例所示?或者有没有更好的方法来完成我正在尝试的任务?

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

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

除非分析表明这确实是一个问题,否则我不会担心它的性能。如果您使用的是IDE,enum方法有打字检查的好处。

除非分析表明这确实是一个问题,否则我不会担心它的性能。如果您使用的是IDE,enum方法有打字检查的好处。

在python中,使用字典进行分派通常比使用大量If/elif/else更有利

因此:

再加上一小段代码就可以自动生成调度表:

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   

在python中,使用字典进行分派通常比使用大量if/elif/else更为有利

因此:

再加上一小段代码就可以自动生成调度表:

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   

我将使用一种组合方法——将“enum”作为标记类的一部分,接受一个字符串进行初始化,然后将其转换。另外,您可以使用dict来创建分派表,而不是使用一堆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()

我将使用一种组合方法——将“enum”作为标记类的一部分,接受一个字符串进行初始化,然后将其转换。另外,您可以使用dict来创建分派表,而不是使用一堆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
,等等)。我认为枚举解决方案的一个优点是它可以清楚地显示允许的值。如果你接受任意字符串,我会说这“更容易出错,也更难记录你的词汇”。例如,
logging
模块对日志级别(例如,
logging.DEBUG
logging.INFO
,等等)使用这种解决方案。是的---这里重要的是拼写检查和指定允许的值,可能不是性能。是的---这里重要的是拼写检查和指定允许的值,可能不是表演。