Style Guide : use *args and **kwargs when subclassing

The “Style Guide for wxPython code” recommends to using *args and
**kwargs when subclassing wx.Windows.

2b. Use *args and **kwargs when subclassing wx.Windows

class MyPanel( wx.Panel ) :

def __init__( self, *args, **kwargs ) :

    wx.Panel.__init__( self, *args, **kwargs )

I would like to know what is recommended when using extra parameters
for the subclass.

Should the parameters be explicitly specified, or through **kwargs ??

class MyPanel( wx.Panel ) :

def __init__( self, bgimage = None, *args, **kwargs ) :

    wx.Panel.__init__( self, *args, **kwargs )

or

class MyPanel( wx.Panel ) :

def __init__( self, *args, **kwargs ) :

    wx.Panel.__init__( self, *args, **kwargs )

    bgimage = kwargs.get( 'bgimage', None )

or some other variation ??

e.g. I’m not sure if the *args should be handled first or can be
safely ignored. I assume, theoretically, it should be handled first,
then search kwargs … correct ??

If so, then it seems to make the constructor methods overly complicated
for each parameter.

Thanks for any comments, advice or recommendations.

Brendan.

···


To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

The “Style Guide for wxPython code” recommends to using *args and **kwargs when subclassing wx.Windows.

2b. Use *args and **kwargs when subclassing wx.Windows

class MyPanel( wx.Panel ) :
def init( self, *args, **kwargs ) :
wx.Panel.init( self, *args, **kwargs )

I would like to know what is recommended when using extra parameters for the subclass.
Should the parameters be explicitly specified, or through **kwargs ??

class MyPanel( wx.Panel ) :
def init( self, bgimage = None, *args, **kwargs ) :
wx.Panel.init( self, *args, **kwargs )
or
class MyPanel( wx.Panel ) :
def init( self, *args, **kwargs ) :
wx.Panel.init( self, *args, **kwargs )
bgimage = kwargs.get( ‘bgimage’, None )
or some other variation ??

e.g. I’m not sure if the *args should be handled first or can be safely ignored. I assume, theoretically, it should be handled first, then search kwargs … correct ??
If so, then it seems to make the constructor methods overly complicated for each parameter.

Thanks for any comments, advice or recommendations.
Brendan.

AFAIK the normal process is to use as args all the parameters that the user must supply and as kwargs those that are optional, i.e. if the documentation of your constructor looks something like:

MyClass MyParrot(Price, Colour=Blue, DeadOrAlive=‘Dead’)

Then Price would the args and Colour & DeadOrAlive would be kwargs.

Hope that helps, (and doesn’t bring too much dissent).

Gadget/Steve

···

From: Brendan Simon (eTRIX)

Sent: Sunday, May 16, 2010 1:46 AM

To: wxPython-users

Subject: [wxPython-users] Style Guide : use *args and **kwargs when subclassing


To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en


To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

I'm not sure you can control that, as the decision as to whether args or
kwargs is used is made by the caller of the function.
i.e. the caller decides whether to code as :
    MyParrot( 34.3, Pink, 'Alive' )
or
    MyParrot( DeadOrAlive = 'Alive', Price = 34.3, Coulour = Pink )

Both calls are completely valid.

I've also found that if you use subclass a few times, then it is
possible to have same keyword appearing multiple times (explicitly and
in kwargs) and a runtime error is generated. I have thus resorted to
specifying all arguments as kwargs, and popping values that are not for
the base class, and specifying kwargs defaults where desired.

    class MyPanel( wx.Panel ) :
       def __init__( self, *args, **kwargs ) :
           fgcolour = kwargs.pop( 'fgcolour' )
           bgimage = kwargs.pop( 'bgimage', None )
           kwargs['title'] = kwargs.get( 'title', 'MyPanel' )
           wx.Panel.__init__( self, *args, **kwargs )

instead of :

    class MyPanel( wx.Panel ) :
       def __init__( self, parent, fgcolour, title = 'MyPanel', bgimage
= None ) :
           wx.Panel.__init__( self, parent = parent, title = title )

or :

    class MyPanel( wx.Panel ) :
       def __init__( self, fgcolour, bgimage = None, *args, **kwargs ) :
           kwargs['title'] = kwargs.get( 'title', 'MyPanel' )
           wx.Panel.__init__( self, *args, **kwargs )

The second method is more standard python and easier to read and understand.
The kwargs method is not as easy to understand at a glance, and it gets
uglier the more parameters there are. I'm also not sure how efficient
it is in terms of performance (presumably ok). However it does have the
advantage that the order of arguments is not important (as is the case
when using constructor defaults), and the problem of multiple keywords
does not occur (important). Maybe just deleting potential multiple
keywords from kwargs is more elegant ??

This still does not cater for args, but if I want to force the caller to
use keywords (which I probably do as it makes code more readable and
reliable), then I guess I could just leave out the args altogether.

An interesting quandary for the style guide. Hopefully a good solution
can be agreed upon and the style guide updated :slight_smile:

Cheers, Brendan.

···

On 16/05/10 4:43 PM, GadgetSteve wrote:

The "Style Guide for wxPython code" recommends to using *args and
**kwargs when subclassing wx.Windows.

    2b. Use *args and **kwargs when subclassing wx.Windows

    class MyPanel( wx.Panel ) :
        def __init__( self, *args, **kwargs ) :
            wx.Panel.__init__( self, *args, **kwargs )

I would like to know what is recommended when using extra parameters for
the subclass.
Should the parameters be explicitly specified, or through **kwargs ??

    class MyPanel( wx.Panel ) :
        def __init__( self, bgimage = None, *args, **kwargs ) :
            wx.Panel.__init__( self, *args, **kwargs )

or

    class MyPanel( wx.Panel ) :
        def __init__( self, *args, **kwargs ) :
            wx.Panel.__init__( self, *args, **kwargs )
            bgimage = kwargs.get( 'bgimage', None )

or some other variation ??

e.g. I'm not sure if the *args should be handled first or can be safely
ignored. I assume, theoretically, it should be handled first, then
search kwargs ... correct ??
If so, then it seems to make the constructor methods overly complicated
for each parameter.

AFAIK the normal process is to use as args all the parameters that the
user *must* supply and as kwargs those that are optional, i.e. if the
documentation of your constructor looks something like:
  MyClass MyParrot(Price, Colour=Blue, DeadOrAlive='Dead')
Then Price would the args and Colour & DeadOrAlive would be kwargs.

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

Brendan Simon (eTRIX) wrote:

I would like to know what is recommended when using extra parameters for
the subclass.

I never could come up with a standard answer for this. Every time I find a solution I like, I need something slightly different and don't like it any more.

    class MyPanel( wx.Panel ) :
        def __init__( self, *args, **kwargs ) :
            wx.Panel.__init__( self, *args, **kwargs )
            bgimage = kwargs.get( 'bgimage', None )

I've found manipulating the kwargs dict always feels awkward, but it does provide flexibility. You should probably use dict.pop() here, and you need to do that before calling the superclass, as the superclass doesn't know what to do with your extra argument.

e.g. I'm not sure if the *args should be handled first or can be safely
ignored. I assume, theoretically, it should be handled first, then
search kwargs ... correct ??

yup.

if the caller specifies a keyword, then it goes into **kwargs, and if not, then it goes into *rags.

AFAIK the normal process is to use as args all the parameters that the
user *must* supply and as kwargs those that are optional

right, so if I _need_ an extra argument on a subclass, then I do:

     def __init__( self, MyRequiredArg, *args, **kwargs )

though this is a bit ugly, because then the parent arg ends up second, which is usually isn't, so sometimes I do:

     def __init__( self, parent, MyRequiredArg, *args, **kwargs )

but that's ugly too, for it's own reasons.

The reason I like to pass *args, **kwargs on through is so that my subclasses support all the arguments of the superclass out of the box. This doesn't, however, always make sense.

My short answer:

What works for you, and let us know if you find an elegant solution!

-Chris

···

On 16/05/10 4:43 PM, GadgetSteve wrote:

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

That's the way I tend to do it. That way the parent arg is always first and can be specified without a keyword, and I can still do the rest of them in any order that makes sense in the context of the caller by specifying them with keyword args.

···

On 5/16/10 12:26 PM, Chris Barker wrote:

so sometimes I do:

def __init__( self, parent, MyRequiredArg, *args, **kwargs )

but that's ugly too, for it's own reasons.

--
Robin Dunn
Software Craftsman

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en