Python - 覆盖__init__的最干净的方法,在super()调用之后必须使用可选的kwarg?

Yuj*_*ita 36 python django

我喜欢蟒蛇的外观/感觉如何美丽,我希望这可以更清洁(可读性很棒).

什么是清洁的方式来推翻子类时要接受一个可选的关键字参数初始化,其中可选的kwarg,必须使用super()电话吗?

我有一个django表单,我想接受一个可选的用户参数,但如果我将其定义为参数之一user=None,那么通常的表单调用form({})假定位置参数引用关键字参数user.

代码说得比(我)的话更好:

def __init__(self, *args, **kwargs):
    user = None
    if 'user' in kwargs:
        user = kwargs.pop('user')
    super(BaseCheckoutForm, self).__init__(*args, **kwargs)
    if user:
        self.prefill_from_user(user)
Run Code Online (Sandbox Code Playgroud)

通过查看实际的Form类来查看它正在查找的参数,我可以使它成为最干净的,但是在python中对子类进行子类化的最大好处之一就是收集所有args并将kwargs其传递给任何子类.此外,这不会影响源中的任何更改.

def __init__(self, querydict=None, user=None):
    super(BaseCheckoutForm, self).__init__(querydict)
    if user:
        self.prefill_from_user(user)
Run Code Online (Sandbox Code Playgroud)

但不幸的是我有:

 def __init__(self, *args, **kwargs):
    # cannot define user=None as an argument because normal usage
    # of class expects a certain order of positional args
    user = None
    if 'user' in kwargs:
        # must pop now since super()__init__ isn't expecting a user kwarg
        user = kwargs.pop('user') 
    super(BaseCheckoutForm, self).__init__(*args, **kwargs)
    if user:
        self.prefill_from_user(user)
Run Code Online (Sandbox Code Playgroud)

感谢您的任何意见!

Joe*_*ton 56

我通常只是做你在这里做的事情.但是,您可以通过提供以下默认参数来缩短/清理代码dict.pop:

 def __init__(self, *args, **kwargs):
    user = kwargs.pop('user', None)
    super(BaseCheckoutForm, self).__init__(*args, **kwargs)
    if user is not None:
        self.prefill_from_user(user)
Run Code Online (Sandbox Code Playgroud)

  • @Yuji - 这绝对是一个不错的功能!不要忘记你可以使用`dict.get`的默认值,以避免`KeyError`.即使``a'不在`x`中时想要避免KeyError,请使用`x.get('a',defaultvalue)`而不是`x ['a']`. (5认同)
  • 哦,非常好!我没有意识到pop有第二个论点.你能告诉我经常不"流行"吗?这有帮助! (3认同)
  • @Joe应该注意虽然[`dict.get()`有'None`作为第二个参数的默认值](https://docs.python.org/2/library/stdtypes.html#dict.get) ,因此它永远不会导致`KeyError` - 它为非耐用键返回`None`. (3认同)