When I define functions, in what order should I put the parameters?

It is often difficult for me to decide, and I disagree. Are there any rules that I could follow?

For example:

def remove_except(haystack, needle, exclude_value): for key in hackstack: if key in needle and haystack[key] != exclude_value: hackstack.pop(key) 

can be easy:

 def remove_except(needle, exclude_value, haystack): for key in hackstack: if key in needle and haystack[key] != exclude_value: hackstack.pop(key) 

Not a perfect example, because I tend to change the variable as the first parameter, for example. haystack, and it might even be a convention, but other than that, I'm not sure what to do.

I'm interested in more languages ​​than just Python.

+7
source share
7 answers

The only rule is to be consistent . This means not only consistency between and within the APIs, but also compatibility with any APIs commonly used in the environment. Please note that this may mean that you are doing something different in one environment than in another. Try to fit in.

Now, using Python and JavaScript, you can use the orientation of the objects to take at least the haystack from the question, because the haystack will (or at least maybe) be the object you act on, and the way you do it will be dictated by the language (for example, delete haystack[needle]; [JavaScript to remove the property from the object] or del haystack[needle] [Python to delete the dictionary entry]). C is not object oriented (C ++, D, Objective-C, and several other derivatives), and so you need to look for convention there.

Subjectively speaking, in my experience, haystack usually in the first place, but it can only be my experience. Likewise, my subjective opinion would be that exclude_value would be the last (so haystack , needle , exclude_value ), because there would be other operations that haystack , needle , something_else would take - but this is just an opinion.

+3
source

I believe that a convention, from left to right, is most important for the least vital. so for your example, I would do (needle, haystack, exclude_value). The needle is the most important in this case because of its defining call information. the same haystack could be used in another call with a different needle. Exclude_value seems like it might be optional.

+1
source

This is very to you. If you write one function that is not similar to anything else in a containing, say, project, then the required / important parameters go first, and then the optional / unimportant trace. The language you use may influence your choices; Python allows you to supply optional named parameters or keyword arguments, but they must follow positional parameters.

If you write a set of similar functions for the API, then the sequence becomes more important. Using the haystack example, you can have

 def insert(haystack, needle) def remove(haystack, needle) def remove_except(haystack, needle, exclude_value) def copy(haystack, haystack2) 

where haystack goes first, because it is a key parameter for all the methods listed and

 def remove(needle, haystack) def remove_except(haystack, needle, exclude_value) 

will look weird (but of course it will work anyway).

If you use an object-oriented language, and you find that you are writing many functions that share a parameter, you will probably think about creating an object and methods of functions that work with this object, but which are likely to go beyond question.

For your chosen language, find a useful code and learn it. If you use Python, check out the standard libraries. For Javascript, jQuery might be good.

+1
source

Just like some supporting information for the chorus “haystack first”, mainly for JavaScript : when you think about which parameter is “most important” or “haystack”, it (can) help you think about which parameter may be different between calls and which is likely to change. In your example, the “needle” is probably quite variable from call to call, while the “haystack” can always or almost always be the same.

Well, if this is the case - that it is common to use such a utility for only one specific object - the "bind ()" method, available in new JavaScript environments (in the Function prototype) or added by a library, for example Prototype or Functional, can be really useful:

 function whatever(haystack, needle) { // ... }; var myHaystack = new Haystack( /* ... */ ); var myHaystackWhatever = whatever.bind(null, myHaystack); 

Now the function "myHaystackWhatever" can be used as follows:

 var result = myHaystackWhatever(someNeedle); 

This may seem trivial, but in a functional language such as JavaScript, the ability to easily and reliably create a new function as a variation of an existing one is very convenient, saving a lot of typing and uneven pair / brackets.

The point here is that objects such as "bind", especially in JavaScript, which has a cleanly ordered binding of call values ​​to formal parameters, you bind in fixed values ​​from left to right. Thus, if your leftmost parameter is most likely for different purposes, then "bind ()" is not very interesting. (The JavaScript functional library has a way to bind other parameters, not only from left to right, but it is quite exotic and strange and, in my opinion, mostly interesting as an example of coding.)

+1
source

I believe that it is entirely up to you.

0
source

In your example, I will start with the object on which the action is being performed or performing the action. Then the most necessary parameters first. So Haystack, a needle, excluded value. If it is possible to have a different version of the function with some parameters reset (for example, an excluded value), they usually go at the end. I think in C right now, but your example is python, so it is possible to handle optional or standard parameters ...

0
source

Besides the “informal” consistency rules or the “most important-least important” rules, there are also some language rules in Python:

A function definition may contain (in this order):

  • positional arguments (i.e. required parameters without a default value),
  • keyword arguments (e.g. optional arguments where the default value is specified during function definition),
  • variable arguments (i.e. an indefinite number of unnamed parameters) and / or
  • keyword variable arguments (i.e. an undefined number of freely-named keyword arguments)

So you can write

 def myfunc(x, y, z=0, truncate=True, *args, **kwargs): do_something() 

which could then be called

 myfunc(1,2) myfunc(1,2,3,False) myfunc(1,2,3,True, "some more args", mykeyword="keyword arg") 

But you cannot define a function like this:

 def wontwork(x=0, y, z): def wontworkeither(*args, debug=True) 

This is described in detail in the Python Tutorial .

0
source

All Articles