使用类型作为字典键被认为是Python中的好习惯吗?

时间:2016-09-14 06:19:10

标签: python python-3.x dictionary

我有一个像这样的查找表:

lookup = {
  "<class 'Minority.mixin'>": report_minority,
  "<class 'Majority.mixin'>": report_majority,
}

def report(o):
  h = lookup[str(type(o))]
  h()

由于keytype()的返回方式不稳定相关,并代表class中的string,因此我看起来很尴尬。如果有一天Python在class中改变了代表string类型的方式,那么这样的所有代码都会被破坏。所以我想从专业人士那里得到一些建议,这种类型的密钥被认为是好还是坏?感谢。

3 个答案:

答案 0 :(得分:2)

问题更多的是你为什么要这样做认为使用字符串有什么好处?

类对象是可清除的,因此您可以直接使用Minority.mixinMajority.mixin 作为键。当你这样做时,你确保密钥总是完全相同的对象,前提是你的类在各自的模块中是全局的,使它们成为你的程序的单例。此外,当您稍后重构代码以重命名模块并且最终得到具有精确repr()输出的不同类型时,不会出现意外混淆的可能性。

因此,除非您具有无法直接使用该类的特定用例,否则不应使用字符串表示。

(即使您要使用工厂函数生成类,使用基类和isinstance检查或从MRO中提取基类可能更可取。)

因此,对于您的用例,坚持:

lookup = {
    Minority.mixin: report_minority,
    Majority.mixin: report_majority,
}

def report(o):
    h = lookup[type(o)])
    h()

接下来,如果您确保report_minorityreport_majority功能(例如,不是方法),您可以使用functools.singledispatch()并免除完全映射:

from functools import singledispatch

@singledispatch
def report(o):
    raise ValueError('Unhandled type {}'.format(type(o)))

@report.register(Minority.mixin)
def report_minority(o):
    # handle a Minority instance

@report.register(Majority.mixin)
def report_majority(o):
    # handle a Majority instance

请注意,这不适用于方法,因为方法必须采用多个参数才能使调度工作,因为它们始终采用self

单一调度处理子类要好得多,不像基于str的映射甚至直接类映射。

答案 1 :(得分:1)

只需从查找和字典中删除str即可。所以

lookup = {
   Minority.mixin : report_minority,
   Majority.mixin : report_majority,
}

def report(o):
    h = lookup[type(o)]
    h()

这可以解决您的直接问题并且是相当合理的代码。但是,似乎调度类型正是OO的用途。那么为什么不在o对象上创建那些不同的报表函数方法呢?然后你可以写:

o.report()

并且可以从班级中获得正确的变体。

答案 2 :(得分:0)

看一下那个剧本,我认为它不是很完美,但它有效,我觉得它比你的解决方案更优雅:

#!/usr/bin/env python3

class Person:
    pass

def display_person():
    print("Person !")

class Car:
    pass

def display_car():
    print("Car !")

lookup = {
    Person: display_person,
    Car: display_car
}


def report(o):
    lookup[o.__class__]()


report(Person())
report(Car())

编辑:修改Python3