python 实例变量初始化代码有味道?

python instance variables initialization code smell?

在下面的两个self.load_file()方法中,第一个没有参数,使用实例变量self.aself.b,第二个使用ab 直接作为输入参数,而 load_file 本质上变成了一个静态方法。它们都达到了相同的目的,哪个是better/preferred,为什么?

其次,如果我有额外的实例变量依赖于前一个,例如self.d = self.do_something_with_file()self.e = self.do_something_with_d(),如果在其中创建实例变量时存在某种连续依赖关系,是否会产生代码味道?例如,如果在 self.file = self.load_file() 期间出现未处理的异常,那么下面的连续链(即 self.dself.e)也会中断。在实践中(尤其是在 larger/production 规模程序中)这种 'consecutive dependency'(我不确定是否有这个术语)样式实例化是否很常见?

class SomeClass:

    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.file = self.load_file()

    def load_file(self):
        for file in os.listdir(config.dir):
            file_split = file.split("_")
            file_a, file_b = file_split[0], file_split[2]

            if file_a == self.a and file_b == self.b:
                try:
                    return pickle.load(open(config.dir + '{}'.format(file), 'rb'))
                except OSError as e:
                    raise Exception("pickle.load error.") from e
        else:
            raise FileNotFoundError('file not found.')

class SomeClass:

    def __init__(self, a, b):
        self.a = a
        self.b = b
        self.file = self.load_file(a, b)

    @staticmethod
    def load_file(a, b):
        for file in os.listdir(config.dir):
            file_split = file.split("_")
            file_a, file_b = file_split[0], file_split[2]

            if file_a == a and file_b == b:
                try:
                    return pickle.load(open(config.dir + '{}'.format(file), 'rb'))
                except OSError as e:
                    raise Exception("pickle.load error.") from e
        else:
            raise FileNotFoundError('file not found.')

如前所述,这是经验和个人品味的问题,但是如果你,假设你有一个 UtilityClass,它封装了这个特定的功能,你将更好的是,如果你需要改变函数中的某些东西,而不用关心这个函数将在哪里使用:

class UtilityClass:

    @staticmethod
    def load_file(a,b):
       ...

class A:
   def __ini__(self, a, b):
       self.a = a
       self.b = b
       self.file = UtilityClass.load_file(a,b)

祝你好运:)

我会使用功能简单的实用程序模块。

# utility.py
from pathlib import Path
import pickle

# default path
default_file = Path("object.foo")

def load_file(file_path: Path = default_file):
    with file_path.open("rb") as file:
       return pickle.load(file)


# main.py
from utility import load_file


class Foo:
    ...

try:
    f = load_file()
except FileNotFoundError:
    f = Foo()
    
assert isinstance(f, Foo)
    

因此文件加载器可以轻松用于任何对象。