Python中带可调用项的多态性

Python中带可调用项的多态性,python,instance,callable,Python,Instance,Callable,我有一个名为iResource的接口类和许多子类,每个子类都实现了“request”方法。请求函数对其他机器使用套接字I/O,因此异步运行它们是有意义的,这样其他机器就可以并行工作 问题是,当我用iResource.request启动一个线程并给它一个子类作为第一个参数时,它将调用超类方法。如果我尝试以“type(a).request”和“a”作为第一个参数开始,那么类型(a)的值将得到“”。你知道这意味着什么,以及如何得到这种方法的真正类型吗?我能以某种方式在Python中正式声明一个抽象方法

我有一个名为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
>>>