【问题标题】:Categorize constants (and be able to determine its category)对常量进行分类(并能够确定其类别)
【发布时间】:2018-09-15 09:52:23
【问题描述】:

我有一些常量(它们类似于错误代码)。

#errors
ERR_ROW_NUM = 1
ERR_COL_NUM = 2
ERR_NUM = 3

#incorrect
INCOR_ROW = 4
INCOR_COL = 5
INCOR_BOX = 6

#warning
WAR_HEAT = 7
WAR_PROCESS = 8

数字是“随机”分配的,无关紧要(重要的是它是唯一的)。然后我有一个将常量与错误消息相关联的字典(见下文)

MSG = {
    ERR_ROW_NUM:"incorrect number of row",
    ERR_COL_NUM:"incorrect number of column",
    ERR_NUM:"an incorrect number in tile detected",

    INCOR_ROW:"repeated number in a row",
    INCOR_COL:"repeated number in a column",
    INCOR_BOX:"repeated number in a small box",

    WAR_HEAT:"some kind of warning message",
    WAR_HARD:"the computer might not be able to handle this",
}

如您所见,常量可以分为以下几类:errorincorrectwarning。 让我们说一个函数generate() 常量之一。如何仅从唯一的常数编号确定常数的“类别”?

我的目标是能够做这样的事情:

output = generate()
category = #somehow get the category from the constant number
print "[ %s ] %s" % (category.upper(), MSG[output].capitalize())

所以如果函数generate()的输出是3,那么它会打印出来:

[ ERROR ] An incorrect number in tile detected

【问题讨论】:

  • 我会研究enum 模块。这在 python2.7 中不可用,但有可用的反向端口。

标签: python python-2.7 constants categories


【解决方案1】:

为类别创建映射:

def catMapper(cat):
    if cat in [1,2,3]:
        return "Error"  # or "ERROR" to save the .upper() below
    elif cat in [4,5,6]:
        return "..."    # Incorrect? ValidationError? pick one.
    elif cat in [7,8]:
        return "Warning"

    raise ValueError('No mapping for {}'.format(cat)) # or return a default of your liking

并在创建错误消息时使用它。

print "[ %s ] %s" % (catMapper(output).upper(), MSG[output].capitalize())

您还可以将每个错误代码映射到 dict 中的另一个常量“CategoryType” - 类似于您对错误消息所做的事情,但我可能会在函数中执行此操作,而不是 dict-lookup。


使用timeit 的dicts 的优势(取自@BlackJack 评论的Dict-Code):

setupDict = """
CAT_TO_NAME = {cat: name for name, cats in [('Error', [1, 2, 3]), ('Incorrect', [4, 5, 6]), ('Warning', [7,8])] for cat in cats}
"""     

testDict = """
for c in range(1,9):
    getIt = CAT_TO_NAME[c]
"""

setupFunc = """
def catMapper(cat):
    if cat in [1,2,3]:
        return "Error"  # or "ERROR" to save the .upper() below
    elif cat in [4,5,6]:
        return "..."    # Incorrect? ValidationError? pick one.
    elif cat in [7,8]:
        return "Warning"

    raise ValueError('No mapping for {}'.format(cat)) # or return a default of your liking
"""

testFunc = """ 
for c in range(1,9):
    getIt = catMapper(c)
"""

import timeit

print(timeit.timeit(testDict,setup = setupDict))
print(timeit.timeit(testFunc,setup = setupFunc))

输出:

0.974066972733   # dictionary lookup
3.08595490456    # functional lookup

结果:

Dict-Lookup 的性能是 3 倍 .... 查找 所有 代码,每次查找 100 万次,对于 dict 和 3s 对于功能查找来说,这还不够。

因此,如果您的主要任务是尽可能快地查找该字符串 900 万次,那么您可以通过使用字典来节省 2 秒的时间...

【讨论】:

  • 为什么要使用缓慢且“复杂”的功能而不是查找字典?我也畏缩看着else 分支。提供既不是错误、不正确或警告但返回警告的 cat 值是等待发生的错误。 :-)
  • @BlackJack 字典需要多个 int->string 映射 - 很多字符串相同。这就是为什么我提到这种可能性,但我更喜欢不这样做。在这种情况下(恕我直言),由于函数调用导致的“缓慢”并不那么重要——除非应用程序所做的只是格式化这种格式字符串。我承认else 有一点 - 我很懒 - 我把它修好了一点,让它变得更好:) 一个人可能应该把所有的消息创建都放在一个函数中,所以你只需调用msg = GetErrorMessage(code) 就可以了- 抽象消息构建。
  • 这不是很多相同的字符串,而是相同的字符串作为不同键的值。 CAT_TO_NAME = {cat:name for name, cat in [('Error', [1, 2, 3]), ('Incorrect', [4, 5, 6]), ('Warning', [7,8])]}
  • @BlackJack 不起作用,列表不可散列。你不能用它们作为关键。您可以改用元组,但这样您就牺牲了在字典中快速查找键的速度。您只有 1 或 2 或 3 而不是 (1,2,3) 作为键 - 因此您需要在所有键上迭代字典并检查每个键元组是否包含给定的代码 - 这也不是一种快速的方法。如果您创建每个单独的代码并将其映射到字符串,您会获得速度,但是您会得到很多重复的文本......因此我更喜欢这个函数。
  • 对不起,我的意思是:CAT_TO_NAME = {cat: name for name, cats in [('Error', [1, 2, 3]), ('Incorrect', [4, 5, 6]), ('Warning', [7,8])] for cat in cats}.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-23
  • 2019-12-06
  • 2010-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多