【发布时间】:2011-09-14 00:15:52
【问题描述】:
我正在尝试继承 type 以创建一个允许构建专用类型的类。例如ListType:
>>> ListOfInt = ListType(list, value_type=int)
>>> issubclass(ListOfInt, list)
True
>>> issubclass(list, ListOfInt)
False
>>> # And so on ...
但是,这个ListOfInt 永远不会用于创建实例!我只是将它用作type 的实例,我可以对其进行操作以与其他类型进行比较...特别是,在我的情况下,我需要根据输入的类型查找合适的操作,并且我需要包含更多精度的类型(如list of int 或XML string 等...)。
这就是我想出的:
class SpzType(type):
__metaclass__ = abc.ABCMeta
@classmethod
def __subclasshook__(cls, C):
return NotImplemented
def __new__(cls, base, **features):
name = 'SpzOf%s' % base.__name__
bases = (base,)
attrs = {}
return super(SpzType, cls).__new__(cls, name, bases, attrs)
def __init__(self, base, **features):
for name, value in features.items():
setattr(self, name, value)
abc 的使用在上面的代码中并不明显......但是如果我想像上面的示例那样编写一个子类 ListType,那么它就变得有用了......
基本功能确实有效:
>>> class SimpleType(SpzType): pass
>>> t = SimpleType(int)
>>> issubclass(t, int)
True
>>> issubclass(int, t)
False
但是当我尝试检查 t 是否是 SpzType 的实例时,Python 吓坏了:
>>> isinstance(t, SpzType)
TypeError: __subclasscheck__() takes exactly one argument (0 given)
我与pdb.pm() 探讨了发生了什么,我发现以下代码引发了错误:
>>> SpzType.__subclasscheck__(SimpleType)
TypeError: __subclasscheck__() takes exactly one argument (0 given)
奇怪?!显然有一个论点......那是什么意思?任何想法 ?我误用了abc 吗?
【问题讨论】:
-
您确定不希望
ABCMeta作为构造类型的元类,而不是您的元类吗? -
如果您想要一种能够理解参数化类型并且可以进行编译时类型检查的语言,那么请使用一种。假设你得到了这个工作,我看不出它怎么可能比仅仅子类化列表和拒绝界面中的非
ints 获得任何东西。 -
@kindall: 嗯......是的,你可能是对的!因为在我的情况下,实例实际上是类型本身,我可能对此感到困惑。想一想,如果我希望我的
ListOfInt被检测为ListOfObject的子类,则 issubclasshook 应该在ListOfObject类上。明天我会试试,如果可行,请发布答案! -
@Karl Knechtel:显然,如果我正在做这样复杂的事情,那是因为我需要!它实际上是针对我正在编写的一个库 (pypi.python.org/pypi/any2any/0.1),而
SpzType的那些实例并不意味着要实例化自己。我只是对定义语义ListOfObject、JSONStr等感兴趣... -
@kindall:即使您可能是对的 - 并且发布的代码无法实现我想要的 - (我还没有尝试过),肯定有一些时髦的事情发生......甚至可能是一个错误,不是吗?