我有几个"型号"可以由具有不同标识符的客户端实例化的类(ModelFoo,ModelBar,ModelBaz,ModelQux)。为了将标识符映射到正确的模型类,我创建了一个映射类:
class ModelTypes(object):
""" Enumeration of supported class types, mapping userland identifier to constructor.
"""
# Multiple names per model type enable us to run several instances in parallel
FooModel = ModelFoo
fooMod = ModelFoo
foo = Foo
ff = Foo
Bar = ModelBar
bar = ModelBar
Baz = ModelBaz
baz = ModelBaz
Qux = ModelQux
qux = ModelQux
@classmethod
def getTypes(cls):
""" Return the names of the attributes explicitly defined above.
"""
for attrName in dir(cls):
attrValue = getattr(cls, attrName)
if (isinstance(attrValue, type) and
issubclass(attrValue, acceptableClassImplementations)):
yield attrName # attrName is an acceptable model name
也就是说,我使用ModelTypes
类进行反向查找,我需要将简单标识符(例如qux
)映射回相应的类(ModelQux
)。但是添加客户端可能使用的所有标识符变得繁琐。是否有标准/建议的方法将关键字映射到类?
答案 0 :(得分:0)
如果您想要的只是更少写入以将多个变量定义为相同的值,则有一种语法:
x = y = z = 0
print(x,y,z)
所以你可以这样做:
FooModel = fooModel = ModelFoo
foo = ff = Foo
Bar = bar = ModelBar
Baz = baz = ModelBaz
Qux = quz = ModelQux
但是如果你想要更自动化的东西,那么你想要一个dict
唯一的内置映射对象,但是它可以被实现为以与项目相同的方式响应属性:
class ModelTypes(dict):
__slots__ = ()#otherwise each object would have a second dict used for attributes
#this will mean d.x acts the same as d['x']
__getattr__ = dict.__getitem__
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
#would you still need this or would you just use .keys() instead?
def getTypes(self): #maybe take an optional argument to use in issubclass()?
return [name for name,cls in self.items() \
if (isinstance(cls,type) and
issubclass(cls, acceptableClassImplementations))]
同样dict
的任何子类都可以定义一个__missing__
方法,如果你试图得到一个不存在的密钥就会被调用,所以你可以实现它再次检查dict忽略大小写并检查类的文档名称:
def __missing__(self,key):
#if the user uses different case this will check again with generic case
#also checks against name attribute of types
if not isinstance(key,str) or key=="":
raise KeyError(key)
key = key.lower()
for name,cls in self.items():
if key == name.lower()):
return cls
if key == getattr(cls,"__name__","").lower():
return cls
raise KeyError(key)
然后您可以定义一个对应于一个类的名称,并且将处理所有变体:
class FooModel:pass
class FooBar:pass
class ModelQux:pass
#other then added commas this is just as clean as inside a class
models = ModelTypes(foo=FooModel,
bar=FooBar,
qux=ModelQux)
print(models.foo is models["foo"]) #.foo works from overriding __getattr__
print(models.foo is models.Foo) #'Foo' works because __missing__ checked it again with lower case
print(models.foo is models.FooModel) #'FooModel' works because __missing__ also checks class names
print(models.foo is models.foomodel) #it checks the .lower() of key against .lower() of class name