Python 抽象方法默认逻辑,super() 方法

Python Abstract Method Default Logic, super() method

我来自 Java 世界,我很难理解与抽象方法相关的 super() 方法。

我有一个带有抽象方法的抽象 class。这个 class' 子 classes 负责查询我的 MySQL 数据库并向我返回格式化报告。在一半的子 class 中,他们使用与 运行 报告完全相同的逻辑。在另一半,每个人都需要自己的逻辑。因此我想使 run_report 成为一个抽象方法。

class Report:
    __metaclass__ = ABCMeta

    def __init__(self):
        self.user = 'root'
        self.passwd = ''
        self.host = '127.0.0.0.1'
        self.port = '80'
        self.db = 'animals'        
        self.conn = mysql.connector.connect(user=self.user, password=self.passd, db=self.db, host=self.host, port=self.port)
        self.cursor = self.conn.cursor()

    @staticmethod
    def construct_query(query, external_data):
        finalQuery = query % external_data
        return finalQuery

    @abstractmethod
    def run_report(self, query):
        self.cursor.execute(self, query)
        results = self.cursor.fetchall()
        return data

这是一个 class 的实现示例,它按原样使用抽象方法:

class SheepReport(Report):

    query = "SELECT COUNT(*) FROM sheep WHERE alive = 1;"

    def run_report(query):
        super(Report, self).run_report(query)

这个语法看起来很神秘。我的代码太不完整,目前无法测试 运行,我正在努力将错误消灭在萌芽状态。我对抽象方法的理解正确吗?

相比之下,这里有一个 class 覆盖了 run_report:

 class CowReport(Report):

    query = "SELECT height, weight FROM cows WHERE name IN (%s);"

    def run_report(self):
        finalQuery = self.construct_query(query, "'Hilda', 'Gary'");
        self.cursor.execute(self, finalQuery)
        results = self.cursor.fetchall()
        return data

我走在正确的轨道上吗?我看到的所有 super() 和继承的例子都让我头疼,我想我需要有人为我简化它。

首先,我真诚地希望这只是为了学习目的,而不是实际的生产代码。将未经过滤的用户输入传递到查询字符串中等于完全成熟的 SQL injection attack.

除此之外...

抽象 classes 通常用于定义接口,而不是具体的功能。不管你想做什么,只有 query 定义为抽象 属性 的抽象 class 会大大简化你的代码。

class Report:
    __metaclass__ = ABCMeta

    def __init__(self):
        self.user = 'root'
        self.passwd = ''
        self.host = '127.0.0.0.1'
        self.port = '80'
        self.db = 'animals'
        self.conn = mysql.connector.connect(user=self.user, password=self.passd, db=self.db, 
                                            host=self.host, port=self.port)
        self.cursor = self.conn.cursor()

    @abstractproperty
    def query(self):
        return NotImplemented

    def construct_query(self, **external_data):
        finalQuery = self.query % external_data
        return finalQuery

    def run_report(self, **external_data):
        self.cursor.execute(self, self.construct_query(**external_data))
        results = self.cursor.fetchall()
        return results

有了上面的class,那么你只需要有一个像下面这样的子class:

class SheepReport(Report):

    @property
    def query(self):
        return "SELECT COUNT(*) FROM sheep WHERE alive = 1;"

不介意无条件self.query % external_data。它将使用模板字符串或带有 字典数据的纯字符串。