动态基类和工厂
我有以下代码:
class EntityBase (object) :
__entity__ = None
def __init__ (self) :
pass
def entity (name) :
class Entity (EntityBase) :
__entity__ = name
def __init__ (self) :
pass
return Entity
class Smth (entity ("SMTH")) :
def __init__ (self, a, b) :
self.a = a
self.b = b
# added after few comments -->
def factory (tag) :
for entity in EntityBase.__subclasses__ () :
if entity.__entity__ == tag :
return entity.__subclasses__ ()[0]
raise FactoryError (tag, "Unknown entity")
s = factory ("SMTH") (1, 2)
print (s.a, s.b)
# <--
现在在工厂中我可以获取 EntityBase 的所有子类,找到“SMTH”的具体子类并创建它。
这是有效的方法还是我可能误解并做错了什么?
I have following code:
class EntityBase (object) :
__entity__ = None
def __init__ (self) :
pass
def entity (name) :
class Entity (EntityBase) :
__entity__ = name
def __init__ (self) :
pass
return Entity
class Smth (entity ("SMTH")) :
def __init__ (self, a, b) :
self.a = a
self.b = b
# added after few comments -->
def factory (tag) :
for entity in EntityBase.__subclasses__ () :
if entity.__entity__ == tag :
return entity.__subclasses__ ()[0]
raise FactoryError (tag, "Unknown entity")
s = factory ("SMTH") (1, 2)
print (s.a, s.b)
# <--
Now in factory I can get all subclasses of EntityBase, find concrete subclass for "SMTH" and create it.
Is this valid approach or maybe I something misunderstood and doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我会用装饰器来做这件事。另外,存储实体->字典中的子类映射允许您用字典查找替换线性扫描。
我不确定 __entity__ 属性是否真的对您有用,或者如果您只是使用它来实现线性扫描。我将其保留在其中,但如果您将其取出,那么与实体关联的类甚至不需要从
EntityBase
继承,您可以将其重命名为Registry
之类的名称。这会浅化您的继承树,并开启在不通过共同血统相关的类上使用的可能性。根据您的用例,更好的方法可能是
装饰器更精美,让我们对自己感觉良好,但字典很简单,有用且切中要害。它很容易理解,也很难出错。除非你真的需要做一些神奇的事情,那么我认为这就是正确的方法。无论如何,你为什么要这样做?
I would do this with a decorator. Also, storing the entity -> subclass map in a dictionary lets you replace a linear scan with a dict lookup.
I'm not sure if the
__entity__
attribute is actually useful to you of if you were just using it to implement the linear scan. I left it in but if you took it out, then the classes associated with entity wouldn't even need to inherit fromEntityBase
and you could rename it to something likeRegistry
. This shallows up your inheritance tree and opens the possibility of using on classes that aren't related through common descent.Depending on what your use case is, a better way to do it might just be
The decorator is fancier and let's us feel nice and fancy about ourselves but the dictionary is plain, useful and to the point. It is easy to understand and difficult to get wrong. Unless you really need to do something magic, then I think that that's the way to go. Why do you want to do this, anyway?
我认为这是您需要 Python 元类:
与您的代码有一些更细微的区别:
entity()
工厂函数创建子类,然后对该子类进行子类化。这种方法不仅创建了不必要的子类,而且还使您的代码无法工作,因为EntityBase.__subclasses__()
不包含Smth
类。__
开头和结尾的标识符是为 Python 保留的,因此我使用_entity_
属性而不是__entity__
。I think this is one of the few cases where you want a Python metaclass:
A few more subtle differences from your code:
entity()
factory function then subclass that subclass. That approach not only creates more subclasses than necessary, but also makes your code not work becauseEntityBase.__subclasses__()
doesn't contain theSmth
class.__
are reserved for Python, so I'm using the_entity_
attribute instead of__entity__
.元类可以跟踪定义的类。当定义具有此元类的类时,
Register.__init__
被调用。我们只需将名称和对象添加到元类中的注册表字典中即可。这样以后就可以直接查找了。顺便说一句,工厂实例化类,因此该名称不适合仅返回类的函数。
A metaclass can keep track of the defined classes.
Register.__init__
is called when a class with this metaclass is defined. We can just add the name and object to a registry dict in the metaclass. This way you can look it up directly later.Btw, a factory instantiates classes, so the name is not fitting for a function that only returns a class.
有用。所以从某种意义上说它是“有效的”。
这完全是浪费代码。所以从某种意义上说,它不是“有效的”。
这种构造没有任何用例。现在您已经构建了它,您可以继续解决实际问题。
It works. So in one sense it's "valid".
It's a complete waste of code. So in one sense it's not "valid".
There aren't any use cases for this kind of construct. Now that you've built it, you can move on to solving practical problems.