用文件中的数据初始化类实例的pythonic方法是什么?

问题描述

我一般不熟悉 OOP 和 Python,但遇到以下问题: 假设我有一个包含要用于创建类实例的逐行数据的文件。处理文件、初始化实例和存储它们的最pythonic 的方法是什么? 我有 3 种替代方法: CASE-1:逐行处理整个文件的类方法,创建实例并将它们存储在列表中 CASE-2:在类之外的功能与 CASE-1 相同 CASE-3:类外的函数分别处理每一行和 main 中的 for 循环 例如:

    class TestClass:
    all_instances_1 = []

    def __init__(self,var1,var2):
        self.var1 = var1
        self.var2 = var2

#CASE-1
    @classmethod
    def from_file(cls,input_file):
        my_file = open(input_file,"r")
        for line in my_file:
            var1,var2 = line.split(',')
            new_instance = TestClass(var1,var2])
            cls.all_instances_1.append(new_instance)
        my_file.close()

#CASE-2
def outside_class_init(input_file):
    all_instances_2 = []
    my_file = open(input_file,"r")
    for line in my_file:
        var1,')
        new_instance = TestClass(var1,var2])
        all_instances_2.append(new_instance)
    my_file.close()
    return all_instances_2

#CASE-3
def one_by_one(my_str):
    var1,')
    new_instance = TestClass(var1,var2])
    return new_instance

def main():
    filename = "$FILE"
    TestClass.from_file(filename)
    instances_list2 = outside_class_init(thefile)

    all_instances_3 = []
    my_file = open(thefile,"r")
    for line in my_file:
        all_instances_3.append(one_by_one(line))
    my_file.close()


if __name__ == '__main__':
    main()

如果它们都不是真正的好方法,您将如何处理? 提前致谢

解决方法

TestClass 结合了两种不同的抽象:一对值的表示,以及这些值对的集合。应该有两个独立的类。举个例子:

class Pair:
    def __init__(self,var1,var2):
        self.var1 = var1
        self.var2 = var2

    @classmethod
    def from_string(cls,s):
        v1,v2 = s.split(",")
        return cls(v1,v2)


class LotsaPairs:
    def __init__(self,pairs):
        self.pairs = pairs

    @classmethod
    def from_file(cls,f):
        return cls([Pair.from_string(line.strip()) for line in f])


def main():
    filename = "$FILE"
    with open(filename) as f:
        all_instances = LotsaPairs.from_file(f)

一些观察:

  1. __init__ 在两个类中都是“哑巴”;它所做的只是用给定的参数初始化属性。

  2. 类方法负责从特定来源“提取”数据以计算 __init__ 的必要值。

  3. LotsaPairs.from_file 接受一个类似文件的对象,而不是文件名。让调用者提供该对象,以进行测试。 (例如,您可以改为传递 io.StringIO 实例。)

  4. LotsaPairs 是一个围绕列表的美化包装器。您可以省去它并用单个函数替换它:

    def get_pairs(f):
        return [Pairs.from_string(line.strip()) for line in f]