有没有一种干净的Pythonic方式可以覆盖Python子类中的默认方法args?

时间:2020-09-29 22:17:34

标签: python oop overriding default

我正在从第三方类继承,并且想要更改该类的方法之一的默认值。我可以想到几种方法,但是没有一种感觉很干净。

所以,如果基类是

class Base:
    def foo(self, a=1, b=2, c=3):
        return a, b, c

我想要一个类MyClass(Base),其中b默认为7。所以,

my_obj = MyClass()
my_obj.foo()  # (1, 7, 3)
my_obj.foo(b=5)  # (1, 5, 3)
my_obj.foo(2, 4)  # (2, 4, 3)
my_obj.foo(8)  # (8, 7, 3)

我已经能够通过手动修改args和kwargs来实现所需的行为,但是感觉并不干净:

class OptionOne(Base):
   
    def foo(self, *args, **kwargs):
        # b is the second argument, so it is an arg if and only if there are 2 or more args
        if len(args) < 2:
            # If b wasn't passed as an arg, update kwargs to default b to 7.
            kwargs['b'] = kwargs.get('b', 7)
        return super().foo(*args, **kwargs)

尝试/排除类型错误似乎比较整洁,但可读性不强:

class OptionTwo(Base):
    
    def foo(self, *args, **kwargs):
        try:
            return super().foo(b=7, *args, **kwargs)
        except TypeError:
            # If b was already specified (as an arg or kwarg) 
            #   "TypeError: foo() got multiple values for keyword argument 'b'"
            # will be raised, so we don't override b in this case.
            return super().foo(*args, **kwargs)

我缺少一种更干净的方法吗?

2 个答案:

答案 0 :(得分:1)

也许尝试以下类似方法。基本上,这将覆盖子类的构造函数中的Route<T> _routeNamed<T>(String name, { @required Object arguments, bool allowNull = false }) { final RouteSettings settings = RouteSettings( name: name, arguments: arguments, ); Route<T> route = widget.onGenerateRoute(settings) as Route<T>; return route; 的默认值。

b

输出:

class Base:
  def __init__(self, a=1, b=2, c=3):
    self.a = a
    self.b = b
    self.c = c

  def print_me(self):
    print(self.a, self.b, self.c)


class MyClass(Base):
   def __init__(self, a=1, b=7, c=3):
        super(MyClass, self).__init__(a, b, c)


test1 = Base()
test1.print_me()

test2 = MyClass()
test2.print_me()

test3 = MyClass(0, 1)
test3.print_me()

test4 = MyClass(b=5)
test4.print_me()

答案 1 :(得分:0)

您可以在定义新方法后手动更改默认值。这不是很好,因为默认值仅存储为元组,而没有任何显式引用它们所应用的参数。

SELECT * FROM TableA 
INNER JOIN TableB ON TableA.Id = TableB.Id AND TableB.Year BETWEEN YEAR(TableA.Date_Start) AND YEAR(TableA.Date_End)

从好的方面来说,这等效于在class OptionTwo(Base): def foo(self, a, b, c): return super().foo(a, b, c) foo.__defaults__ = (Base.foo.__defaults__[:1] + (7,) + Base.foo.__defaults__[2:]) 本身的定义中设置默认值,但是不需要您实际知道旧的默认值。

如果愿意,还可以将其抽象为装饰器。

foo