Python中带可调用项的多态性
我有一个名为iResource的接口类和许多子类,每个子类都实现了“request”方法。请求函数对其他机器使用套接字I/O,因此异步运行它们是有意义的,这样其他机器就可以并行工作 问题是,当我用iResource.request启动一个线程并给它一个子类作为第一个参数时,它将调用超类方法。如果我尝试以“type(a).request”和“a”作为第一个参数开始,那么类型(a)的值将得到“”。你知道这意味着什么,以及如何得到这种方法的真正类型吗?我能以某种方式在Python中正式声明一个抽象方法吗 编辑:包括代码Python中带可调用项的多态性,python,instance,callable,Python,Instance,Callable,我有一个名为iResource的接口类和许多子类,每个子类都实现了“request”方法。请求函数对其他机器使用套接字I/O,因此异步运行它们是有意义的,这样其他机器就可以并行工作 问题是,当我用iResource.request启动一个线程并给它一个子类作为第一个参数时,它将调用超类方法。如果我尝试以“type(a).request”和“a”作为第一个参数开始,那么类型(a)的值将得到“”。你知道这意味着什么,以及如何得到这种方法的真正类型吗?我能以某种方式在Python中正式声明一个抽象方法
def getSocialResults(self, query=''):
#for a in self.types["social"]: print type(a)
tasks = [type(a).request for a in self.types["social"]]
argss = [(a, query, 0) for a in self.types["social"]]
grabbers = executeChainResults(tasks, argss)
return igrabber.cycleGrabber(grabbers)
“executeChainResults”接受可调用的“任务”列表和args元组的“argss”列表,并假设每个返回一个列表。然后,它在一个单独的线程中执行每个线程,并连接结果列表。如果需要的话,我可以发布代码,但是我没有遇到任何问题,所以我现在就不发布了
对象“a”绝对不是iResource类型,因为它有一个只抛出异常的构造函数。但是,将“type(a).request”替换为“iResource.request”将调用基类方法。此外,直接调用“self.types[“social”][0].request”也可以,但上面的代码给出了:“type object'instance'没有属性'request'”
取消注释注释注释行会打印几次。您可以只使用绑定方法对象本身:
tasks = [a.request for a in self.types["social"]]
# ^^^^^^^^^
grabbers = executeChainResults(tasks, [(query, 0)] * len(tasks))
# ^^^^^^^^^^^^^^^^^^^^^^^^^
如果坚持通过基类调用方法,也可以这样做:
from abc import ABCMeta
from functools import wraps
def virtualmethod(method):
method.__isabstractmethod__ = True
@wraps(method)
def wrapper(self, *args, **kwargs):
return getattr(self, method.__name__)(*args, **kwargs)
return wrapper
class IBase(object):
__metaclass__ = ABCMeta
@virtualmethod
def my_method(self, x, y):
pass
class AddImpl(IBase):
def my_method(self, x, y):
return x + y
class MulImpl(IBase):
def my_method(self, x, y):
return x * y
items = [AddImpl(), MulImpl()]
for each in items:
print IBase.my_method(each, 3, 4)
b = IBase() # <-- crash
从abc导入ABCMeta
从functools导入包装
def虚拟方法(方法):
方法.\uuuu isabstractmethod\uuuu=True
@包装(方法)
def包装器(自身、*args、**kwargs):
返回getattr(self,method.\uuuuuu name)(*args,**kwargs)
返回包装器
类IBase(对象):
__元类_uu=ABCMeta
@虚拟方法
定义my_方法(self、x、y):
通过
类AddImpl(IBase):
定义my_方法(self、x、y):
返回x+y
类MulImpl(IBase):
定义my_方法(self、x、y):
返回x*y
items=[AddImpl(),MulImpl()]
对于每个项目:
打印IBase.my_方法(每个,3,4)
b=IBase()#=2.6。在Python中使用“旧样式类”时,对“
”的引用-即:不是从“对象”类型层次结构派生的类。旧样式的类不应该与语言的一些较新特性一起工作,包括描述符和其他特性。而且,除其他事项外,-您不能使用正在执行的操作从旧样式类的类中检索属性(或方法):
>>> class C(object):
... def c(self): pass
...
>>> type (c)
<class '__main__.C'>
>>> c = C()
>>> type(c).c
<unbound method C.c>
>>> class D: #not inheriting from object: old style class
... def d(self): pass
...
>>> d = D()
>>> type(d).d
>>> type(d)
<type 'instance'>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'instance' has no attribute 'd'
>>>
在这里,我调用类“a”中的一个方法,给它一个特殊的“a”实例-该方法仍然是类“a”中的一个方法。您能展示一些代码吗?在我看来,这是不应该发生的。你需要仔细阅读Duck-typing的概念。请,无论你做什么,从对象
开始编写你的类,这是自Python 2.2以来正确的做法
>>> class C(object):
... def c(self): pass
...
>>> type (c)
<class '__main__.C'>
>>> c = C()
>>> type(c).c
<unbound method C.c>
>>> class D: #not inheriting from object: old style class
... def d(self): pass
...
>>> d = D()
>>> type(d).d
>>> type(d)
<type 'instance'>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'instance' has no attribute 'd'
>>>
>>> class A(object):
... def b(self):
... print "super"
...
>>> class B(A):
... def b(self):
... print "child"
...
>>> b = B()
>>> A.b(b)
super
>>>