CodeQL 文档

__init__ 方法调用重写方法

ID: py/init-calls-subclass
Kind: problem
Security severity: 
Severity: warning
Precision: high
Tags:
   - reliability
   - correctness
Query suites:
   - python-security-and-quality.qls

点击查看 CodeQL 代码库中的查询

当初始化类的实例时,超类状态应该在它对子类可见之前完全初始化。在超类的 __init__ 方法中调用子类的方法违反了这个重要的不变式。

建议

不要在对象构建中使用被子类化的方法。对于更简单的案例,将初始化移到超类的 __init__ 方法中,防止它被重写。子类的额外初始化应该在子类的 __init__ 方法中完成。对于更复杂的案例,建议使用静态方法或函数来管理对象创建。

或者,使用组合而不是继承来完全避免继承。

示例

#Superclass __init__ calls subclass method

class Super(object):

    def __init__(self, arg):
        self._state = "Not OK"
        self.set_up(arg)
        self._state = "OK"

    def set_up(self, arg):
        "Do some set up"

class Sub(Super):

    def __init__(self, arg):
        Super.__init__(self, arg)
        self.important_state = "OK"

    def set_up(self, arg):
        Super.set_up(self, arg)
        "Do some more set up" # Dangerous as self._state is "Not OK"


#Improved version with inheritance:

class Super(object):

    def __init__(self, arg):
        self._state = "Not OK"
        self.super_set_up(arg)
        self._state = "OK"

    def super_set_up(self, arg):
        "Do some set up"


class Sub(Super):

    def __init__(self, arg):
        Super.__init__(self, arg)
        self.sub_set_up(self, arg)
        self.important_state = "OK"


    def sub_set_up(self, arg):
        "Do some more set up"


参考资料

  • ©GitHub, Inc.
  • 条款
  • 隐私