如何将要由子类实现的空函数包装到tryexcept块中?

2024-05-06 12:32:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在创建一个抽象的网络爬虫类爬虫。 此类只能与实现某些方法的子类一起使用。在

(删除了init方法,因为它是无关的)

class Crawler():
    def get_image_source_url(self, image_page_soup):
        return NotImplementedError("method get_image_source_url must be implemented")

    def get_image_thumbnail_url(self, image_page_soup):
        return NotImplementedError("method get_image_thumbnail_url must be implemented")

    def get_tags_container(self, image_page_soup):
        return NotImplementedError("method get_tags_container must be implemented")

它们在子类中是这样实现的:

^{pr2}$

我想把函数包装在try-except块中,不管它是如何实现的。所以最终的结果是:(伪代码)

class Crawler():
    def get_image_source_url(self, image_page_soup):
        if not_implemented:
            return NotImplementedError("method get_image_thumbnail_url must be implemented")
        else:
            try:
            whatever the child class chooses to do
            except Exception:
            handle exception however i decide in the parent class

我不知道如何检查它是否已实现,以及如何在不覆盖所有子类的情况下包装函数,我是否清楚我要实现的目标?在


Tags: imageselfurlgetreturndefpagebe
3条回答

Note: This post contains two different implementation techniques to allow for what you want.


间接求解

解决此问题的最简单方法是重构代码,使子类不直接重写公共接口使用的函数。在

相反,直接在基类中提供公共功能,并使子级重写所述函数的“worker”(实现细节),该函数稍后由从外部调用的函数调用。在


示例实现

class Base (object):
    def get_message (self):
        try:
            return self.get_message_impl ()
        except Exception as detail:
            print ("error:", detail)    
        return None

    def get_message_impl (self):
        raise Exception ("Not Implemented")
^{pr2}$
class Bar (Base):
    def get_message_impl (self):
        raise Exception ("Bar.get_message_impl always fails!")
f = Foo ()
b = Bar ()

f_msg = f.get_message ()
b_msg = b.get_message ()

print ("f_msg:", f_msg)
print ("b_msg:", b_msg)

输出

error: Bar.get_message_impl always fails!
f_msg: Hello World
b_msg: None


选择保护

如果您希望保持重写基类中呈现的公共功能的可能性,同时在以后仍然能够轻松调用函数的“protected”版本,则可以创建一个简单的包装器,如下所示:

class Base (object):
    class Protected (object):
        def __init__ (self, target):
            self.target = target

        def get_message (self):
            try:
                return self.target.get_message ()
            except Exception as detail:
                print ("error:", detail)
            return None

    def __init__ (self):
        self.protected = self.Protected (self)

    def get_message (self):
        raise Exception ("Not Implemented")
class Foo (Base):
    def get_message (self):
        return "Hello World";
class Bar (Base):
    def get_message (self):
        raise Exception ("Bar.get_message_impl always fail!")
f = Foo ()
b = Bar ()

f_msg = f.protected.get_message () # protected from failure
b_msg = b.protected.get_message () # protected from failure

b_msg = b.get_message ()           # will raise exception

NotImplementedError是一个异常;不要返回它,将其作为异常引发:

class Crawler():
    def get_image_source_url(self, image_page_soup):
        raise NotImplementedError("method get_image_source_url must be implemented")

    def get_image_thumbnail_url(self, image_page_soup):
        raise NotImplementedError("method get_image_thumbnail_url must be implemented")

    def get_tags_container(self, image_page_soup):
        raise NotImplementedError("method get_tags_container must be implemented")

你不需要在这里“包装”任何东西。如果子类实现该方法,则不会调用原始方法,并且不会引发异常。在

如果需要进一步处理,并且子类实现是可选的,但外部API不应可见,则可以要求子类使用不同的名称来实现方法,从基类方法调用:

^{pr2}$

这里self.get_image_source_url()委托给可选的self._image_source_url_implementation()方法。在

如果要将子类型的实现包装在某个东西中,则需要使用不同的方法名。例如:

class Crawler:
    def get_image_source_url(self, image_page_soup):
        try:
            self._get_image_source_url(image_page_soup)
        except NotImplementedError:
            raise
        except Exception:
            print('Some exception occurred, fall back to something else')
            # …

    def _get_image_source_url(self, image_page_soup):
        raise NotImplementedError()

class ChildCrawler(Crawler):
    def _get_image_source_url(self, image_page_soup):
        doStuff()

相关问题 更多 >