Joh*_*nes 57 python constructor initialization idiomatic initializer
我有一个容纳数据的容器类.创建容器时,有不同的方法来传递数据.
在Java中,我将创建三个构造函数.以下是在Python中可能出现的情况:
class Container:
def __init__(self):
self.timestamp = 0
self.data = []
self.metadata = {}
def __init__(self, file):
f = file.open()
self.timestamp = f.get_timestamp()
self.data = f.get_data()
self.metadata = f.get_metadata()
def __init__(self, timestamp, data, metadata):
self.timestamp = timestamp
self.data = data
self.metadata = metadata
Run Code Online (Sandbox Code Playgroud)
在Python中,我看到了三个明显的解决方案,但它们都不是很漂亮:
答:使用关键字参数:
def __init__(self, **kwargs):
if 'file' in kwargs:
...
elif 'timestamp' in kwargs and 'data' in kwargs and 'metadata' in kwargs:
...
else:
... create empty container
Run Code Online (Sandbox Code Playgroud)
B:使用默认参数:
def __init__(self, file=None, timestamp=None, data=None, metadata=None):
if file:
...
elif timestamp and data and metadata:
...
else:
... create empty container
Run Code Online (Sandbox Code Playgroud)
C:仅提供构造函数来创建空容器.提供使用来自不同来源的数据填充容器的方法.
def __init__(self):
self.timestamp = 0
self.data = []
self.metadata = {}
def add_data_from_file(file):
...
def add_data(timestamp, data, metadata):
...
Run Code Online (Sandbox Code Playgroud)
解决方案A和B基本相同.我不喜欢做if/else,特别是因为我必须检查是否提供了此方法所需的所有参数.如果要通过第四种方法扩展代码来添加数据,则A比B更灵活.
解决方案C似乎是最好的,但用户必须知道他需要哪种方法.例如:c = Container(args)如果他不知道是什么,他就不能这样做args.
什么是最恐怖的解决方案?
gle*_*oux 76
您不能拥有多个具有相同名称的方法Python.函数重载 - 与in不同Java- 不受支持.
使用默认参数或**kwargs和*args参数.
您可以使用@staticmethodor @classmethoddecorator 创建静态方法或类方法以返回类的实例,或添加其他构造函数.
我建议你这样做:
class F:
def __init__(self, timestamp=0, data=None, metadata=None):
self.timestamp = timestamp
self.data = list() if data is None else data
self.metadata = dict() if metadata is None else metadata
@classmethod
def from_file(cls, path):
_file = cls.get_file(path)
timestamp = _file.get_timestamp()
data = _file.get_data()
metadata = _file.get_metadata()
return cls(timestamp, data, metadata)
@classmethod
def from_metadata(cls, timestamp, data, metadata):
return cls(timestamp, data, metadata)
@staticmethod
def get_file(path):
# ...
pass
Run Code Online (Sandbox Code Playgroud)
⚠在python中永远不要将可变类型作为默认值.⚠见这里.
900*_*000 25
您不能拥有多个构造函数,但可以使用多个适当命名的工厂方法.
class Document(object):
def __init__(self, whatever args you need):
"""Do not invoke directly. Use from_NNN methods."""
# Implementation is likely a mix of A and B approaches.
@classmethod
def from_string(cls, string):
# Do any necessary preparations, use the `string`
return cls(...)
@classmethod
def from_json_file(cls, file_object):
# Read and interpret the file as you want
return cls(...)
@classmethod
def from_docx_file(cls, file_object):
# Read and interpret the file as you want, differently.
return cls(...)
# etc.
Run Code Online (Sandbox Code Playgroud)
但是,您无法轻易阻止用户直接使用构造函数.(如果它很关键,作为开发过程中的安全预防措施,您可以在构造函数中分析调用堆栈,并检查调用是否来自其中一个预期的方法.)
| 归档时间: |
|
| 查看次数: |
12068 次 |
| 最近记录: |