Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何要求抽象方法是协同程序?_Python_Abstract Class_Python Asyncio - Fatal编程技术网

Python 如何要求抽象方法是协同程序?

Python 如何要求抽象方法是协同程序?,python,abstract-class,python-asyncio,Python,Abstract Class,Python Asyncio,如何要求抽象基类将特定方法实现为协同路由。例如,考虑ABC: import abc class Foo(abc.ABC): @abc.abstractmethod async def func(): pass 现在,当我将其子类化并实例化时: class Bar(Foo): def func(): pass b = Bar() 虽然func与ABC中的async不同,但这一操作成功。只有当func是async时,才能成功执行此操作。

如何要求抽象基类将特定方法实现为协同路由。例如,考虑ABC:

import abc

class Foo(abc.ABC):
    @abc.abstractmethod
    async def func():
        pass
现在,当我将其子类化并实例化时:

class Bar(Foo):
    def func():
        pass

b = Bar()

虽然
func
与ABC中的
async
不同,但这一操作成功。只有当
func
async
时,才能成功执行此操作。

您可以使用
\uuuu new\uuu
并检查子类是否以及如何重写父类的CORO

import asyncio
import abc
import inspect


class A:    

    def __new__(cls, *arg, **kwargs):
        # get all coros of A
        parent_coros = inspect.getmembers(A, predicate=inspect.iscoroutinefunction)

        # check if parent's coros are still coros in a child
        for coro in parent_coros:
            child_method = getattr(cls, coro[0])
            if not inspect.iscoroutinefunction(child_method):
                raise RuntimeError('The method %s must be a coroutine' % (child_method,))

        return super(A, cls).__new__(cls, *arg, **kwargs)

    @abc.abstractmethod
    async def my_func(self):
        pass


class B(A):

    async def my_func(self):
        await asyncio.sleep(1)
        print('bb')


class C(A):

    def my_func(self):
        print('cc')

async def main():
    b = B()
    await b.my_func()

    c = C()  # this will trigger the RuntimeError
    await c.my_func()


loop = asyncio.get_event_loop()
loop.run_until_complete(main())
警告
  • 子类也可以重写
    \uuuuu new\uuuu
    以抑制此约束
  • 不仅可以等待
    async
    。比如说

    async def _change_in_db(self, key, value):
        # some db logic
        pass
    
    def change(self, key, value):
        if self.is_validate(value):
            raise Exception('Value is not valid')
        return self._change_in_db(key, value)  
    
    可以像这样调用
    change

    await o.change(key, value)
    
    更不用说对象、其他原始未来、任务中的
    \uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu


这个问题的可能重复之处在于如何测试,这只是解决方案的一部分。我想使用一个抽象基类来实现这一点。您必须在class
Bar
中再次定义
async def func()
@abc.abstractmethod
不考虑
func()
是否异步。是的,我理解。我想问的是,除了编写自定义的元类之外,是否还有一种方法可以实现这一点。在类内测试函数
func()
是一种方法,但它不是您想要的!谢谢,这非常有用,包括解决方案和注意事项!我认为有必要补充一点,即不建议将
*args
**kwargs
传递到
\uuuuuuuu新的\uuuuuuuu
而不是
\uuuuu初始\uuuuuuu
。由于Python 3.3+很可能会抛出一个错误(如果您这样做的话)。AFAIR.
\uuuuu new\uuuu
可以接受第一个类以外的参数(3.3+不会抛出任何错误),
\uuuu new\uuuu
是一个与其他任何函数一样的函数,所以为什么不起作用呢。
\uuuu init\uuuu
是对象的initlializer,而这里是使用类创建的方法——这是一种不同的方法。