多个构造函数:Python方式? [英] Multiple constructors: the Pythonic way?

查看:235
本文介绍了多个构造函数:Python方式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个容纳数据的容器类。创建容器时,有多种传递数据的方法。


  1. 传递包含数据的文件

  2. 直接通过参数传递数据

  3. 不传递数据;只需创建一个空容器

在Java中,我将创建三个构造函数。如果可能的话,这就是Python的样子:

 类容器:

def __init__ (自我):
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 =时间戳记
self.data =数据
self.metadata =元数据

在Python中,我看到了三个明显的解决方案,但它们都不是很漂亮的:



A :使用关键字参数:

  def __init __(self,** kwargs ):
如果在kwargs中使用'file':
...
elif在kwargs中使用'timestamp'在kwargs中使用'data'而在kwargs中使用'metadata':
...
其他:
...创建空容器

B :使用默认参数:

  def __init __(self,file = None,timestamp = None,data = None,metadata = None):
如果文件:
...
elif时间戳以及数据和元数据:
...
其他:
...创建空容器

C :仅提供构造函数来创建空容器。提供使用不同来源的数据填充容器的方法。

  def __init __(self):
self.timestamp = 0
self.data = []
self.metadata = {}

def add_data_from_file(file):
...

def add_data(时间戳,数据,元数据):
...

解决方案A和B是基本相同。我不喜欢if / else,尤其是因为我必须检查是否提供了此方法所需的所有参数。如果要通过第四种方法扩展代码以添加数据,则A比B灵活。



解决方案C似乎是最好的方法,但是用户必须知道他需要哪种方法。例如:如果他不知道 args 是什么,他就不能做 c = Container(args)



最Python化的解决方案是什么?

解决方案

不能有多个 Python 中具有相同名称的方法。不支持函数重载-与 Java 不同-



使用默认参数或 ** kwargs * args 参数。



您可以创建静态方法或类 @staticmethod @classmethod 装饰器的方法返回类的实例,或添加其他构造函数。 / p>

我建议您这样做:

  F类:

def __init __(self,timestamp = 0,data = None,metadata = None):
self.timestamp = timestamp
self.data = list()如果data为none,则数据
self.metadata = dict()如果元数据为其他元数据

@classmethod
def from_file(cls,path):
_file = cls.get_file(path)
时间戳= _file.get_timestamp()
数据= _file.get_data()
元数据= _file.get_metadata()
return cls(时间戳,数据,元数据)

@classmet hod
def from_metadata(cls,时间戳,数据,元数据):
return cls(时间戳,数据,元数据)

@staticmethod
def get_file(path):
#...
通过




⚠永远不要将可变类型作为python中的默认值。 ⚠
参见此处

>


I have a container class that holds data. When the container is created, there are different methods to pass data.

  1. Pass a file which contains the data
  2. Pass the data directly via arguments
  3. Don't pass data; just create an empty container

In Java, I would create three constructors. Here's how it would look like if it were possible in 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

In Python, I see three obvious solutions, but none of them is pretty:

A: Using keyword arguments:

def __init__(self, **kwargs):
    if 'file' in kwargs:
        ...
    elif 'timestamp' in kwargs and 'data' in kwargs and 'metadata' in kwargs:
        ...
    else:
        ... create empty container

B: Using default arguments:

def __init__(self, file=None, timestamp=None, data=None, metadata=None):
    if file:
        ...
    elif timestamp and data and metadata:
        ...
    else:
        ... create empty container

C: Only provide constructor to create empty containers. Provide methods to fill containers with data from different sources.

def __init__(self):
    self.timestamp = 0
    self.data = []
    self.metadata = {}

def add_data_from_file(file):
    ...

def add_data(timestamp, data, metadata):
    ...

Solutions A and B are basically the same. I don't like doing the if/else, especially since I have to check if all arguments required for this method were provided. A is a bit more flexible than B if the code is ever to be extended by a fourth method to add data.

Solution C seems to be the nicest, but the user has to know which method he requires. For example: he cant do c = Container(args) if he doesn't know what args is.

Whats the most Pythonic solution?

解决方案

You can't have multiple methods with same name in Python. Function overloading - unlike in Java - isn't supported.

Use default parameters or **kwargs and *args arguments.

You can make static methods or class methods with the @staticmethod or @classmethod decorator to return an instance of your class, or to add other constructors.

I advise you to do:

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

⚠ Never have mutable types as defaults in python. ⚠ See here.

这篇关于多个构造函数:Python方式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆