对 config.py 使用 class 继承可能有哪些缺点?
What would be the possible drawbacks of using class inheritance for config.py?
我一直在尝试想出在 Python 项目中处理配置的最佳方法,我决定继续创建 config.py
并将所有配置作为 classes.
然而,我发现:
- 如果您想要多个配置,最好有某种形式的“基本”配置。
- 有时在
dict
中获取配置在您必须将其放入某些函数参数时会派上用场。
所以我创建了我自己的方式来处理config.py
的配置:
- 在我创建任何新配置时继承
BaseConfig
NewConfig
- 继承
@classmethod
即 returns 所有 class 变量作为 dict
。
但是,由于我是从头开始创建这段代码的,所以我想知道是否有任何可能的副作用,以后会让我后悔。
我不确定的一件事是继承 class 个变量是否是个好主意。
此外,我设法使 get_dict()
工作,但我不知道它的机制是否良好且可扩展。
下面是我的代码:
class BaseConfig:
ROOT_DIR = Path('.').resolve()
print_every = 2000
epochs = 3
lr = 1e-5
batch_size = 1
loss = "CrossEntropyLoss"
optim = "SGD"
@classmethod
def get_dict(cls):
if cls is BaseConfig:
cls_dict = {k:v for k, v in cls.__dict__.items() if not k.startswith('_') and k != "get_dict"}
else:
cls_dict = BaseConfig.get_dict()
cls_dict.update({k:v for k, v in cls.__dict__.items() if not k.startswith('_') and k != "get_dict"})
return cls_dict
class NewConfig(BaseConfig):
epochs = 2
lr = 5e-5
optim = "Adam"
dataset = "CIFAR10"
我已经为我自己的一些项目做过这样的配置,我认为它工作得相当好。在大多数情况下,我认为继承 class 属性不是问题。
我能想到的一些缺点包括:
重用 parent class 中的 class 属性可能会有点尴尬,因为你无法说“parent class's 属性”来自 child class 而没有明确说明 parent。例如,如果您希望您的配置属性之一是 child classes 可以添加到的列表,您要么需要这样的东西:
class A:
my_property = ["a"]
class B(A):
my_property = A.my_property + ["b"]
或者这个:
class A:
my_property = ["a"]
class B(A):
pass
B.my_property = B.my_property + ["b"]
我觉得两者都不是特别好,但这对你来说可能不是什么大问题。
这种配置需要用户了解一些基本的Python。 (当然,根据应用程序,这可能不是问题。)
对于某些用户,包括那些熟悉 Python 的用户,这种配置似乎有悖常理。我知道有些人觉得必须编写 Python 代码作为配置很奇怪,甚至更奇怪的是将配置变成 classes.
关于 get_dict
实现——您可以使用 dir
来简化它。例如,
@classmethod
def get_dict(cls):
return {k:getattr(cls,k) for k in dir(cls) if not k.startswith("_") and k != "get_dict"}
这应该适用于您 BaseConfig
的任何后代。
但是,这种方法有一个问题。如果您想向任何 class 中添加更多方法或 class 方法,则需要相应地更新 get_dict
;这是一个痛苦,是 error-prone。对于省略方法,您可以尝试这样的方法。
@classmethod
def get_dict(cls):
return {k:getattr(cls,k) for k in dir(cls) if not k.startswith("_") and not callable(getattr(cls,k))}
我认为除非您的某些配置参数是函数,否则这应该能正常工作。在这种情况下,您可能不得不求助于维护应由 get_dict
.
返回的参数的白名单
我一直在尝试想出在 Python 项目中处理配置的最佳方法,我决定继续创建 config.py
并将所有配置作为 classes.
然而,我发现:
- 如果您想要多个配置,最好有某种形式的“基本”配置。
- 有时在
dict
中获取配置在您必须将其放入某些函数参数时会派上用场。
所以我创建了我自己的方式来处理config.py
的配置:
- 在我创建任何新配置时继承
BaseConfig
NewConfig
- 继承
@classmethod
即 returns 所有 class 变量作为dict
。
但是,由于我是从头开始创建这段代码的,所以我想知道是否有任何可能的副作用,以后会让我后悔。
我不确定的一件事是继承 class 个变量是否是个好主意。
此外,我设法使 get_dict()
工作,但我不知道它的机制是否良好且可扩展。
下面是我的代码:
class BaseConfig:
ROOT_DIR = Path('.').resolve()
print_every = 2000
epochs = 3
lr = 1e-5
batch_size = 1
loss = "CrossEntropyLoss"
optim = "SGD"
@classmethod
def get_dict(cls):
if cls is BaseConfig:
cls_dict = {k:v for k, v in cls.__dict__.items() if not k.startswith('_') and k != "get_dict"}
else:
cls_dict = BaseConfig.get_dict()
cls_dict.update({k:v for k, v in cls.__dict__.items() if not k.startswith('_') and k != "get_dict"})
return cls_dict
class NewConfig(BaseConfig):
epochs = 2
lr = 5e-5
optim = "Adam"
dataset = "CIFAR10"
我已经为我自己的一些项目做过这样的配置,我认为它工作得相当好。在大多数情况下,我认为继承 class 属性不是问题。
我能想到的一些缺点包括:
重用 parent class 中的 class 属性可能会有点尴尬,因为你无法说“parent class's 属性”来自 child class 而没有明确说明 parent。例如,如果您希望您的配置属性之一是 child classes 可以添加到的列表,您要么需要这样的东西:
class A: my_property = ["a"] class B(A): my_property = A.my_property + ["b"]
或者这个:
class A: my_property = ["a"] class B(A): pass B.my_property = B.my_property + ["b"]
我觉得两者都不是特别好,但这对你来说可能不是什么大问题。
这种配置需要用户了解一些基本的Python。 (当然,根据应用程序,这可能不是问题。)
对于某些用户,包括那些熟悉 Python 的用户,这种配置似乎有悖常理。我知道有些人觉得必须编写 Python 代码作为配置很奇怪,甚至更奇怪的是将配置变成 classes.
关于 get_dict
实现——您可以使用 dir
来简化它。例如,
@classmethod
def get_dict(cls):
return {k:getattr(cls,k) for k in dir(cls) if not k.startswith("_") and k != "get_dict"}
这应该适用于您 BaseConfig
的任何后代。
但是,这种方法有一个问题。如果您想向任何 class 中添加更多方法或 class 方法,则需要相应地更新 get_dict
;这是一个痛苦,是 error-prone。对于省略方法,您可以尝试这样的方法。
@classmethod
def get_dict(cls):
return {k:getattr(cls,k) for k in dir(cls) if not k.startswith("_") and not callable(getattr(cls,k))}
我认为除非您的某些配置参数是函数,否则这应该能正常工作。在这种情况下,您可能不得不求助于维护应由 get_dict
.