__init__
方法调用重写方法¶
ID: py/init-calls-subclass
Kind: problem
Security severity:
Severity: warning
Precision: high
Tags:
- reliability
- correctness
Query suites:
- python-security-and-quality.qls
当初始化类的实例时,超类状态应该在它对子类可见之前完全初始化。在超类的 __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"
参考资料¶
CERT 安全编码: 规则 MET05-J。虽然这是一个 Java 规则,但它适用于大多数面向对象的语言。
Python 标准库: 静态方法。
维基百科: 组合优于继承。