我在一个项目中有一个类,它根据初始化时的条件实现一组动态绑定方法。这样做的目的是通过创建一个包含一系列绑定到对象的方法的新模块,使库的功能易于扩展,同时也简化了库的API,使之不积极参与其中。在
这不是一个完美的并行,但是为了表示这一点,我将使用一个Dog
类,该类在初始化时从tricks模块获取一系列技巧,在本例中,它将作为包含模块名称的字符串传递。在
class Dog(object):
def __init__(self, name, module_name):
self.name = name
# imports module
module = __import__("mylib.tricks.{mod}".format(mod=module_name),
from_list=['arbitrary argument'])
# Dog object gets all tricks from module as bound methods
tricks = module.__all__
for trick in tricks:
exec("self." + trick + "=types.MethodType(" + trick + ", self)")
然后,由于这些方法将被指定为绑定方法,因此tricks模块可以包含访问类属性的方法,例如:
^{pr2}$现在我终于到了我挣扎的那部分了。使用ABCMeta
类__subclasshook__
方法可以更改is instance()
方法的行为,以便它为实现特定方法的任何类返回true。例如,我们可以有一个DuckABC
抽象基类,它本质上是一个接口,对于实现quack()
方法的任何类也返回true。在
class DuckABC:
__metaclass__=ABCMeta
@abstractmethod
def quack(self):
pass
@classmethod
def __subclasshook__(cls, instance):
if cls is DuckABC:
if any("quack" in class_.__dict__ for class_ in instance.__mro__):
return True
return NotImplemented
class Cat(object):
def __init__(self, name):
self.name=name
def quack(self):
# Not a very talented cat
print 'meow'
>>> my_cat = Cat('Tom')
>>> isinstance(my_cat, DuckABC)
True
然而,这就是我的问题所在。使用这个DuckABC
抽象基类和上面定义的动态Dog
类,以下情况是正确的:
>>> my_dog = Dog('Berkley', 'name_of_module_containing_quack')
>>> my_dog.quack()
Quack!
>>> isinstance(my_dog, DuckABC)
False
我理解它没有返回true,因为Dog
类本身没有任何称为quack
的方法,尽管{
所以我的问题是:在这个框架中有没有任何方法可以使用isinstance()
方法来检查我的dog类的特定实例是否知道如何嘎嘎作响?如果没有,我还有什么选择可以实现相同的功能?在
使用
hasattr
:我想说得简单得多:
所以您的
^{pr2}$tricks
模块将包含mixin。您可以创建一个工厂函数来生成所需类的子类/实例:相关问题 更多 >
编程相关推荐