首页 > 解决方案 > 为类构造函数提供默认值的大多数 Python 方式

问题描述

我试图坚持谷歌的风格指南,从一开始就力求一致性。

我目前正在创建一个模块,在这个模块中我有一个类。我想为不同的标准用例提供一些合理的默认值。但是,我想让用户灵活地覆盖任何默认值。我目前正在做的是提供一个模块范围的“常量”字典,其中包含默认值(针对不同的用例),并且在我的类中,我将构造函数中的参数优先于默认值。

最后,我想确保我们以参数的有效值结束。

这就是我所做的:

MY_DEFAULTS = {"use_case_1": {"x": 1, "y": 2},
               "use_case_2": {"x": 4, "y": 3}}

class MyClass:
   def __init__(self, use_case = None, x = None, y = None):
      self.x = x
      self.y = y
      if use_case:
         if not self.x:
            self.x = MY_DEFAULTS[use_case]["x"]
         if not self.y:
            self.y = MY_DEFAULTS[use_case]["y"]
      assert self.x, "no valid values for 'x' provided"
      assert self.y, "no valid values for 'y' provided"
   def __str__(self):
      return "(%s, %s)" % (self.x, self.y)  

print(MyClass()) # AssertionError: no valid values for 'x' provided
print(MyClass("use_case_1")) # (1, 2)
print(MyClass("use_case_2", y = 10) # (4, 10)

问题

标签: python

解决方案


一般来说,如果有不止一种方法可以合理地构造你的对象类型,你可以提供classmethods来替代构造(dict.fromkeys这是一个很好的例子)。请注意,如果您的用例是有限的且静态定义良好,则此方法更适用。

class MyClass:
   def __init__(self, x, y):
      self.x = x
      self.y = y
   @classmethod
   def make_use_case1(cls, x=1, y=2):
       return cls(x,y)
   @classmethod
   def make_use_case2(cls, x=4, y=3):
       return cls(x,y)

   def __str__(self):
      return "(%s, %s)" % (self.x, self.y)  

如果用例中唯一的变化是默认参数,那么每次重写位置参数列表是很多开销。相反,我们可以编写一个classmethod仅将用例和可选覆盖作为关键字。

class MyClass:
    DEFAULTS_PER_USE_CASE = {
        "use_case_1": {"x": 1, "y": 2},
        "use_case_2": {"x": 4, "y": 3}
    }
    @classmethod
    def make_from_use_case(cls, usecase, **overrides):
        args = {**cls.DEFAULTS_PER_USE_CASE[usecase], **overrides}
        return cls(**args)

    def __init__(self, x,y):
        self.x = x
        self.y = y

    def __str__(self):
        return "(%s, %s)" % (self.x, self.y)

x = MyClass.make_from_use_case("use_case_1", x=5)
print(x)

如果您希望按位置传递参数,那将更加困难,但我想这将满足您的需求。


推荐阅读