views:

95

answers:

7

In python you may have a function definition:

def info(object, spacing=10, collapse=1)

which could be called in any of the following ways:

info(odbchelper)                    
info(odbchelper, 12)                
info(odbchelper, collapse=0)        
info(spacing=15, object=odbchelper)

thanks to python's allowing of any-order arguments, so long as they're named.

The problem we're having is as some of our larger functions grow, people might be adding parameters between spacing and collapse, meaning that the wrong values may be going to parameters that aren't named. In addition sometimes it's not always clear as to what needs to go in. We're after a way to force people to name certain parameters - not just a coding standard, but ideally a flag or pydev plugin?

so that in the above 4 examples, only the last would pass the check as all the parameters are named.

Odds are we'll only turn it on for certain functions, but any suggestions as to how to implement this - or if it's even possible would be appreciated.

A: 

You could use the ** operator:

def info(**kwargs):

this way people are forced to use named parameters.

Olivier
A: 

You could declare your functions as receiving **args only. That would mandate keyword arguments but you'd have some extra work to make sure only valid names are passed in.

def foo(**args):
   print args

foo(1,2) # Raises TypeError: foo() takes exactly 0 arguments (2 given)
foo(hello = 1, goodbye = 2) # Works fine.
Noufal Ibrahim
+8  A: 

This isn't a coding problem, it's a social problem. By creating the code you are creating a contract -- give me these arguments in this order and I'll give you a result. Sometime later, someone is choosing to break that contract. To what end? Why would someone on your team think it's OK to make a backwards-incompatible change in such a manner?

Bryan Oakley
+1: "people might be adding parameters between spacing and collapse"? Really? Who are those people who might be doing this? Find them and help them see the error of their ways or help them find jobs for which they are more suited.
S.Lott
My view is that anyone changing code should always search to see if they break something else as a result - functions calling it is one of these basic checks. Unfortunately not everyone seems to hold that view.
Mark Mayo
@Mark Mayo: If they can't run unit tests to locate breakage, they need career coaching.
S.Lott
+2  A: 
Felix Kling
I liked your old answer better. Just put a comment as to why you are only accepting **kwargs in the function. After all, anyone can change anything in source code -- you need documentation to describe intent and purpose behind your decisions.
Brandon Corfman
A: 
def cheeseshop(kind, *arguments, **keywords):

in python if use *args that means you can pass n-number of arguments for this parameter - which will be come a list inside function to access

and if use **kw that means its keyword arguments, that can be access as dict - you can pass n-number of kw args, and if you want to restrict that user must enter the sequence and arguments in order then don't use * and ** - (its pythonic way to provide generic solutions for big architectures...)

if you want to restrict your function with default values then you can check inside it

def info(object, spacing, collapse)
  spacing = spacing or 10
  collapse = collapse or 1
Tumbleweed
A: 

As other answers say, changing function signatures is a bad idea. Either add new parameters to the end, or fix every caller if arguments are inserted.

If you still want to do it, use a function decorator and the inspect.getargspec function. It would be used something like this:

@require_named_args
def info(object, spacing=10, collapse=1):
    ....

Implementation of require_named_args is left as an exercise for the reader.

I would not bother. It will be slow every time the function is called, and you will get better results from writing code more carefully.

Daniel Newby
A: 

I don't get why a programmer will add a parameter in between two others in the first place.

If you want the function parameters to be used with names (e.g. info(spacing=15, object=odbchelper) ) then it shouldn't matter what order they are defined in, so you might as well put the new parameters at the end.

If you do want the order to matter then can't expect anything to work if you change it!

Umang