这是一个尝试创建一个装饰器的玩具示例,该装饰器允许声明属性名称,这应该是标准__subclasshook__
和__instancecheck__
模式中“接口检查”的必需部分。
Foo
当我装饰班级时,它似乎按预期工作。我创建了一个Bar
与 无关的类Foo
,但它具有所需的属性,并且正确满足isinstance(instance_of_bar, Foo) == True
.
但是作为另一个例子,我创建了一个dict
augmented 的子类,这样这些key
值也可以通过getattr
语法访问(例如,可以用dict
whered['a']
替换d.a
以获得相同的结果)。在这种情况下,属性只是实例属性,所以__instancecheck__
应该可以工作。
这是代码。请注意,鉴于带有实例的示例,将函数Bar
“monkeypatch”到类(具有元类)中的选择可以正常工作。所以似乎不必直接在元类的类定义中定义函数。__subclasshook__
Foo
#Using Python 2.7.3
import abc
def interface(*attributes):
def decorator(Base):
def checker(Other):
return all(hasattr(Other, a) for a in attributes)
def __subclasshook__(cls, Other):
if checker(Other):
return True
return NotImplemented
def __instancecheck__(cls, Other):
return checker(Other)
Base.__subclasshook__ = classmethod(__subclasshook__)
Base.__instancecheck__ = classmethod(__instancecheck__)
return Base
return decorator
@interface("x", "y")
class Foo(object):
__metaclass__ = abc.ABCMeta
def x(self): return 5
def y(self): return 10
class Bar(object):
def x(self): return "blah"
def y(self): return "blah"
class Baz(object):
def __init__(self):
self.x = "blah"
self.y = "blah"
class attrdict(dict):
def __getattr__(self, attr):
return self[attr]
f = Foo()
b = Bar()
z = Baz()
t = attrdict({"x":27.5, "y":37.5})
print isinstance(f, Foo)
print isinstance(b, Foo)
print isinstance(z, Foo)
print isinstance(t, Foo)
印刷:
True
True
False
False
这只是一个玩具示例——我不是在寻找更好的方法来实现我的attrdict
课程。该Bar
示例演示了猴子补丁的__subclasshook__
工作方式。其他两个示例演示了__instancecheck__
仅具有要检查的实例属性的实例的失败。在那些情况下,__instancecheck__
甚至没有调用。
我可以手动检查(即,根据需要)或__instancecheck__
的实例是否满足我的函数的条件。attrdict
hasattr(instance_of_attrdict, "x")
True
z
同样,对于Bar
. 这表明__subclasshook__
装饰器正在正确应用,并且修补自定义__metaclass__
不是问题。但是__instancecheck__
在这个过程中似乎没有被调用。
为什么可以__subclasshook__
在元类的类定义之外定义并在以后添加,但不能__instancecheck__
?