max*_*max 16 python oop abstract-class software-design
class ABC是一个"抽象基类".class X是它的子类.
有些工作需要在任何子类中完成ABC,这很容易忘记或做错.我想ABC.__init__()通过以下两种方式来帮助解决这些错误:
(1)开始这项工作,或(2)验证它
这会影响super().__init__()是在开始时还是在结束时调用X.__init__().
以下是用于说明目的的简化示例:
假设每个子类ABC必须具有一个属性registry,并且它必须是一个列表.ABC.__init__()可以(1)初始化registry或(2)检查它是否正确创建.以下是每种方法的示例代码.
方法1:在ABC中初始化
class ABC:
def __init__(self):
self.registry = []
class X:
def __init__(self):
super().__init__()
# populate self.registry here
...
Run Code Online (Sandbox Code Playgroud)
方法2:在ABC中验证
class ABC:
class InitializationFailure(Exception):
pass
def __init__(self):
try:
if not isinstance(self.registry, list):
raise ABC.InitializationError()
except AttributeError:
raise ABC.InitializationError()
class X:
def __init__(self):
self.registry = []
# populate self.registry here
...
super().__init__()
Run Code Online (Sandbox Code Playgroud)
哪个更好的设计?
小智 14
当然,人们更倾向于方法1接近2(因为方法2将基础降级为标记接口而不是实现抽象功能).但是,方法1本身并不能满足您防止子类型开发人员忘记正确实现super()调用,确保初始化的目标.
您可能希望查看"工厂"模式以减轻子类型实现者忘记初始化的可能性.考虑:
class AbstractClass(object):
'''Abstract base class template, implementing factory pattern through
use of the __new__() initializer. Factory method supports trivial,
argumented, & keyword argument constructors of arbitrary length.'''
__slots__ = ["baseProperty"]
'''Slots define [template] abstract class attributes. No instance
__dict__ will be present unless subclasses create it through
implicit attribute definition in __init__() '''
def __new__(cls, *args, **kwargs):
'''Factory method for base/subtype creation. Simply creates an
(new-style class) object instance and sets a base property. '''
instance = object.__new__(cls)
instance.baseProperty = "Thingee"
return instance
Run Code Online (Sandbox Code Playgroud)
这个基类可以比方法1更简单地扩展,只使用三(3)行代码san-commment,如下所示:
class Sub(AbstractClass):
'''Subtype template implements AbstractClass base type and adds
its own 'foo' attribute. Note (though poor style, that __slots__
and __dict__ style attributes may be mixed.'''
def __init__(self):
'''Subtype initializer. Sets 'foo' attribute. '''
self.foo = "bar"
Run Code Online (Sandbox Code Playgroud)
请注意,虽然我们没有调用超类的构造函数,但是baseProperty将被初始化:
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from TestFactory import *
>>> s = Sub()
>>> s.foo
'bar'
>>> s.baseProperty
'Thingee'
>>>
Run Code Online (Sandbox Code Playgroud)
正如其注释所示,基类AbstractClass不需要使用槽,它可以通过在new()初始化器中设置它们来轻松地"隐式"定义属性.例如:
instance.otherBaseProperty = "Thingee2"
Run Code Online (Sandbox Code Playgroud)
会工作得很好.另请注意,基类的初始化程序在其子类型中支持普通(无arg)初始化程序,以及可变长度的arugmented和关键字参数初始值设定项.我建议始终使用此表单,因为它不会在最简单(简单的构造函数)情况下强加语法,但允许更复杂的功能而不强加维护.
| 归档时间: |
|
| 查看次数: |
13075 次 |
| 最近记录: |