Python - 在super()调用后使用可选kwarg时,最简洁的__init__重写方法是什么?

38 投票
1 回答
37390 浏览
提问于 2025-04-16 12:00

我很喜欢Python的美观和感觉,希望能让代码更简洁(可读性真棒)。

有没有什么好的方法来接受一个可选的关键字参数,当我在子类中重写init方法时,这个可选的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)

我可以通过查看实际的Form类来找到它需要什么参数,这样可以让代码更整洁,但在Python中,子类化的一个最大好处就是可以收集所有的argskwargs,然后把它们传递给你所继承的类。而且这样做也不容易受到源代码变化的影响。

def __init__(self, querydict=None, user=None):
    super(BaseCheckoutForm, self).__init__(querydict)
    if user:
        self.prefill_from_user(user)

但不幸的是,我遇到了:

 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)

感谢任何建议!

1 个回答

60

我通常也是像你这样做。不过,你可以通过给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)

撰写回答