python 实例变量初始化代码有味道?
python instance variables initialization code smell?
在下面的两个self.load_file()
方法中,第一个没有参数,使用实例变量self.a
和self.b
,第二个使用a
和b
直接作为输入参数,而 load_file
本质上变成了一个静态方法。它们都达到了相同的目的,哪个是better/preferred,为什么?
其次,如果我有额外的实例变量依赖于前一个,例如self.d = self.do_something_with_file()
和 self.e = self.do_something_with_d()
,如果在其中创建实例变量时存在某种连续依赖关系,是否会产生代码味道?例如,如果在 self.file = self.load_file()
期间出现未处理的异常,那么下面的连续链(即 self.d
和 self.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)
因此文件加载器可以轻松用于任何对象。
在下面的两个self.load_file()
方法中,第一个没有参数,使用实例变量self.a
和self.b
,第二个使用a
和b
直接作为输入参数,而 load_file
本质上变成了一个静态方法。它们都达到了相同的目的,哪个是better/preferred,为什么?
其次,如果我有额外的实例变量依赖于前一个,例如self.d = self.do_something_with_file()
和 self.e = self.do_something_with_d()
,如果在其中创建实例变量时存在某种连续依赖关系,是否会产生代码味道?例如,如果在 self.file = self.load_file()
期间出现未处理的异常,那么下面的连续链(即 self.d
和 self.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)
因此文件加载器可以轻松用于任何对象。