假设我有一个类,它有一个成员叫做data,它是一个列表。

我希望能够初始化类,例如,一个文件名(包含初始化列表的数据)或一个实际的列表。

你的技巧是什么?

你只是通过查看__class__来检查类型吗?

我是不是漏掉了什么技巧?

我习惯了c++,在那里根据参数类型重载很容易。


当前回答

非常好的问题。我也解决了这个问题,虽然我同意“工厂”(类方法构造函数)是一个很好的方法,但我想建议另一个我也发现非常有用的方法:

下面是一个示例(这是一个read方法而不是构造函数,但思想是相同的):

def read(self, str=None, filename=None, addr=0):
    """ Read binary data and return a store object. The data
        store is also saved in the interal 'data' attribute.

        The data can either be taken from a string (str 
        argument) or a file (provide a filename, which will 
        be read in binary mode). If both are provided, the str 
        will be used. If neither is provided, an ArgumentError 
        is raised.
    """
    if str is None:
        if filename is None:
            raise ArgumentError('Please supply a string or a filename')

        file = open(filename, 'rb')
        str = file.read()
        file.close()
    ...
    ... # rest of code

这里的关键思想是使用Python对命名参数的出色支持来实现这一点。现在,如果我想从文件中读取数据,我说:

obj.read(filename="blob.txt")

为了从字符串中读取它,我说:

obj.read(str="\x34\x55")

这样用户就只有一个方法可以调用。如您所见,在内部处理它并不过于复杂

其他回答

我喜欢的解决方案是:

class MyClass:
    _data = []
    __init__(self,data=None):
        # do init stuff
        if not data: return
        self._data = list(data) # list() copies the list, instead of pointing to it.

然后使用MyClass()或MyClass([1,2,3])调用它。

希望这能有所帮助。编码快乐!

在python3中,你可以像Python Cookbook中写的那样使用函数注释实现多分派:

import time


class Date(metaclass=MultipleMeta):
    def __init__(self, year:int, month:int, day:int):
        self.year = year
        self.month = month
        self.day = day

    def __init__(self):
        t = time.localtime()
        self.__init__(t.tm_year, t.tm_mon, t.tm_mday)

它是这样工作的:

>>> d = Date(2012, 12, 21)
>>> d.year
2012
>>> e = Date()
>>> e.year
2018

你应该使用isinstance

isinstance(...)
    isinstance(object, class-or-type-or-tuple) -> bool

    Return whether an object is an instance of a class or of a subclass thereof.
    With a type as second argument, return whether that is the object's type.
    The form using a tuple, isinstance(x, (A, B, ...)), is a shortcut for
    isinstance(x, A) or isinstance(x, B) or ... (etc.).

你可能需要isinstance内置函数:

self.data = data if isinstance(data, list) else self.parse(data)

非常好的问题。我也解决了这个问题,虽然我同意“工厂”(类方法构造函数)是一个很好的方法,但我想建议另一个我也发现非常有用的方法:

下面是一个示例(这是一个read方法而不是构造函数,但思想是相同的):

def read(self, str=None, filename=None, addr=0):
    """ Read binary data and return a store object. The data
        store is also saved in the interal 'data' attribute.

        The data can either be taken from a string (str 
        argument) or a file (provide a filename, which will 
        be read in binary mode). If both are provided, the str 
        will be used. If neither is provided, an ArgumentError 
        is raised.
    """
    if str is None:
        if filename is None:
            raise ArgumentError('Please supply a string or a filename')

        file = open(filename, 'rb')
        str = file.read()
        file.close()
    ...
    ... # rest of code

这里的关键思想是使用Python对命名参数的出色支持来实现这一点。现在,如果我想从文件中读取数据,我说:

obj.read(filename="blob.txt")

为了从字符串中读取它,我说:

obj.read(str="\x34\x55")

这样用户就只有一个方法可以调用。如您所见,在内部处理它并不过于复杂