处理重载的最“python”方法

2024-05-13 00:38:08 发布

您现在位置:Python中文网/ 问答频道 /正文

免责声明:这可能是一个非常主观的问题,没有“正确”的答案,但如果您能就最佳实践和程序设计提供任何反馈,我将不胜感激。所以这里是:

我正在编写一个库,其中文本文件被读入Text对象。现在可以用文件名列表或直接用Sentence对象列表初始化这些文件。我想知道最好/最具Python风格的方法是什么,因为如果我理解正确的话,Python不直接支持方法重载。在

我在Scikit-Learnfeature extraction module中找到的一个例子就是在初始化对象时将输入的类型作为参数传递。我假设一旦设置了这个参数,就只需要在内部处理不同的情况:

if input == 'filename':
    # glob and read files
elif input == 'content':
    # do something else

虽然这很容易实现,但看起来不是一个非常优雅的解决方案。所以我想知道是否有更好的方法来处理多种类型的输入来初始化我忽略的类。在


Tags: 文件对象方法答案text声明列表input
2条回答

您可以使用duck typing。首先,假设参数是X类型,如果它们引发异常,那么假设它们是Y类型,依此类推:

class Text(object):
    def __init__(self, *init_vals):
        try:
            fileobjs = [open(fname) for fname in init_vals]
        except TypeError:
            # Then we consider them as file objects.
            fileobjs = init_vals

        try:
            senteces = [parse_sentences(fobj) for fobj in fileobjs]
        except TypeError:
            # Then init_vals are Sentence objects.
            senteces = fileobjs

注意,缺少类型检查意味着该方法实际上接受实现您实际使用的接口之一的任何类型(例如file-类对象,Sentence-类对象等)。在

如果你想支持很多不同的类型,这个方法会变得很重,但是我认为这是糟糕的代码设计。接受超过2,3,4个类型作为初始值设定项可能会让任何使用您的类的程序员感到困惑,因为他总是会想“等等,是不是X也接受了Y,或者是{}接受了Y……”。在

最好将构造函数设计为只接受2,3个不同的接口,并向用户提供一些函数/类,允许用户将一些常用类型转换为这些接口。在

一种方法是为实例化对象的不同方式创建具有不同名称的类方法:

class Text(object):
    def __init__(self, data):
        # handle data in whatever "basic" form you need

    @classmethod
    def fromFiles(cls, files):
        # process list of filenames into the form that `__init__` needs
        return cls(processed_data)

    @classmethod
    def fromSentences(cls, sentences):
        # process list of Sentence objects into the form that `__init__` needs
        return cls(processed_data)

这样,您只需创建一个“real”或“canonical”初始化方法,该方法接受您想要的任何“最小公分母”格式。专用的fromXXX方法可以对不同类型的输入进行预处理,以将它们转换为传递给规范实例化所需的形式。其思想是调用Text.fromFiles(...)从文件名生成Text,或调用{}从句子对象生成Text。在

如果您只想接受几种可枚举类型的输入之一,也可以接受一些简单的类型检查。例如,类接受文件名(作为字符串)或file对象并不少见。在这种情况下,你应该:

^{pr2}$

如果有许多不同类型的输入要处理,这会变得很难处理,但是如果它是这样相对包含的东西(例如,可以用来获取对象的对象或字符串“name”),那么它可能比我展示的第一个方法更简单。在

相关问题 更多 >