我有一个像这样的查找表:
lookup = {
"<class 'Minority.mixin'>": report_minority,
"<class 'Majority.mixin'>": report_majority,
}
def report(o):
h = lookup[str(type(o))]
h()
由于key
与type()
的返回方式不稳定相关,并代表class
中的string
,因此我看起来很尴尬。如果有一天Python在class
中改变了代表string
类型的方式,那么这样的所有代码都会被破坏。所以我想从专业人士那里得到一些建议,这种类型的密钥被认为是好还是坏?感谢。
答案 0 :(得分:2)
问题更多的是你为什么要这样做? 你认为使用字符串有什么好处?
类对象是可清除的,因此您可以直接使用Minority.mixin
和Majority.mixin
作为键。当你这样做时,你确保密钥总是完全相同的对象,前提是你的类在各自的模块中是全局的,使它们成为你的程序的单例。此外,当您稍后重构代码以重命名模块并且最终得到具有精确repr()
输出的不同类型时,不会出现意外混淆的可能性。
因此,除非您具有无法直接使用该类的特定用例,否则不应使用字符串表示。
(即使您要使用工厂函数生成类,使用基类和isinstance
检查或从MRO中提取基类可能更可取。)
因此,对于您的用例,坚持:
lookup = {
Minority.mixin: report_minority,
Majority.mixin: report_majority,
}
def report(o):
h = lookup[type(o)])
h()
接下来,如果您确保report_minority
和report_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