Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

django - Python - Cleanest way to override __init__ where an optional kwarg must be used after the super() call?

I love how beautiful python looks/feels and I'm hoping this can be cleaner (readability is awesome).

What's a clean way to accept an optional keyword argument when overriding a subclassed init where the optional kwarg has to be used after the super() call?

I have a django form where I'd like to accept an optional user argument, but if I define it as one of the arguments user=None, then the usual form call form({}) assumes the positional argument refers to the keyword argument user.

Code speaks better than (my) words:

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)

I can make this the cleanest by looking into the actual Form class to see what arguments it's looking for, but one of the greatest things about subclassing anything in python is collecting all args and kwargs and passing it into whatever you subclassed. Also this doesn't hold up to any changes in the source.

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

But unfortunately I have:

 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)

Thanks for any input!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I usually just do essentially what you're doing here. However, you can shorten/clean up your code by supplying a default argument to 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)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...