【问题标题】:More efficient approach of creating class instances of different classes?创建不同类的类实例的更有效方法?
【发布时间】:2018-08-16 03:23:42
【问题描述】:

假设我们有一个函数classes_init。它接收列表或其他类型的信息,用于初始化不同类型类的许多实例,例如:

["spam", 24]
["eggs", 10]
["bacon", 20]
...

这些列表的索引 0 表示它应该是什么类型的类。我发现初始化特定类实例的最佳方法是通过以下方式:

def classes_init(xlists):
    classlist = list()
    if xlists[0] == "spam":
        classlist.append(Spam(number=xlists[1]))
    elif xlists[0] == "eggs":
        classlist.append(Eggs(number=xlists[1]))
    elif xlists[0] == "bacon":
        classlist.append(Bacon(number=xlists[1]))
    ... and so on ...

有没有更有效的方法来做到这一点?这是很多重复,所以几乎可以肯定,这是一种错误的方法。

【问题讨论】:

    标签: python python-3.x class oop initialization


    【解决方案1】:

    使用字典将字符串映射到类:

    class_map = {
        'spam': Spam,
        'eggs': Eggs,
        'bacon': Bacon,
    }
    
    def classes_init(xlists):
        classlist = [class_map[name](argument) for name, argument in xlists]
    

    如果所有字符串都对应于小写名称,则可以从类名创建类映射:

    classes = (Spam, Eggs, Bacon)
    class_map = {cls.__name__.lower(): cls for cls in classes}
    

    【讨论】:

    • 如果您可以按照 OP 的要求添加如何实例化类 n 次的代码会很酷。
    • 字典是一个很好的答案,但我对列表推导不太熟悉。那里到底发生了什么?我正在使用您所说明的代码进行测试,并且不断收到ValueError: too many values to unpack (expected 2) 等等。
    • @Holsterbau:列表推导式只是一个优化的list.append() 循环。所以对于每次迭代,都会附加class_map[name](argument) 的结果,并且迭代来自for name, argument in xlists。您的错误出现在 for 循环端,它要求 xlists 中的所有元素都是两个值的序列(因此您的问题中的列表、元组或其他可以产生 2 个值的东西),错误表明xlists 列表中的至少一个元素只有一个元素。
    • @Holsterbau:请参阅 Python for-in loop preceded by a variable 以获得更全面的列表推导解释。
    【解决方案2】:

    删除if-elif 结构并将其添加到您的代码中:

    exec("classList.append(" + xlists[0].title() + "(number = xlists[1])")
    

    这样,与手动将数据输入dict 相比,需要更少的内存和更少的时间,但如果xlists 包含格式化为代码的字符串,则可能会更危险,因此请确保在运行之前清理字符串代码。

    【讨论】:

    • 我怀疑exec 比使用dict 更快
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 2012-10-26
    • 2011-08-24
    • 2018-11-23
    • 2012-09-22
    相关资源
    最近更新 更多