1

I was wondering if there is a best practice or a convention for this kind of "chained" named parameter. I am trying to pass the first variable d to bar through foo. It is kind of awkward to do it this way and I believe there should be a smarter way but after looking through tons of documents today still no clue.

def bar(a=0, b=0, c=0, d=0):
    print(a,b,c,d)

def foo(b=0,d=0):
    bar(d=d)

foo(d=1)
#(0,0,0,1)
Bill Cheng
  • 732
  • 1
  • 8
  • 15
  • 2
    In `foo`, you are calling `test()`. Is that supposed to be `bar()`? – ToMakPo Feb 23 '17 at 00:17
  • 1
    also why dose `foo` have a `b` parameter if it is not being used? – ToMakPo Feb 23 '17 at 00:18
  • Sorry typo...fixed it. – Bill Cheng Feb 23 '17 at 00:20
  • 3
    There are cases where a language ought to require explicit text to express what's happening. This is one. I've worked in a language that makes parameters of the caller available in the callee. It's more-or-less a disaster. If you mean to pass a map, then pass a (hash) map. – Gene Feb 23 '17 at 00:20
  • ``foo`` has ``b`` as an argument is just an assumption there should be lots of other variables in the function which are used in other situations. Thanks! – Bill Cheng Feb 23 '17 at 00:21
  • If you don't mind `foo` being somewhat generified and losing its defaults then you could simply make `foo`s signature `foo(**kwargs)` and forward the arguments on to `bar` like `bar(**kwargs)`. I don't think you'll be able to have it both ways and forward on argument to `bar` and have defaults in `foo` too. – Paul Rooney Feb 23 '17 at 00:37

3 Answers3

0

I don't think there is a better way of doing this, but if the b parameter is not going to be used in foo() then I wouldn't have it in there.

def bar(a=0, b=0, c=0, d=0):
    print(a,b,c,d)

def foo(d=0):
    bar(d=d)

foo(1)
#(0,0,0,1)
ToMakPo
  • 855
  • 7
  • 27
0

Any answer here is subjective but I'm not going to submit to close the question because I think this is valuable for anyone learning Python and professional practice.

With that said, I think the way you have it is correct, if b in foo is assumed to be used in a line of code within the function after bar is called. If b isn't used, you should remove it from the parameter list.

But let me make another case while we're at subjectivity: specify arguments upon a function call by use of keyword arguments as much as possible.

Why?

Because when you're looking at complex code in a professional environment, it becomes much more clear what's being passed into a function and why. And in Python, explicit is preferred over implicit.

You will write your code once. You might correct it a couple of times. Someone will read your code to handle a production issue a thousand times.

Take for example the below code (which is a financial model):

def black_scholes(spot, strike, volatility, risk_free_rate, expiry=.25):
    # do calculation and return result
    # ....
    return result

option_value = black_scholes(44, 48, .08, .54, .75)

Put your hand over the parameter list in the function definition. Can you tell what each of those numbers represents? Sure, you can find the definition in the same file and compare the positional arguments, but what if black_scholes() is in another module? Now it's a tiny bit tougher. What if we expanded on this and added a higher-leveled wrapper around black_scholes() and that's what we had to debug to get to this?

Now, let me show you the function call with keyword arguments:

result = black_scholes(spot=44, strike=48, volatility=.08, risk_free_rate=.54, expiry=.75)

This now becomes much more clear, and we can anticipate what the expected result should be. We also just saved a lot of time on reading the code and have a result to compare with (given the expected) from stepping over the function in the debugger instead of having to go into it and reading it line by line.

the_constant
  • 681
  • 4
  • 11
0

It's not specific to Python, but what is asked looks much like a classical code smell, which are mostly language agnostic.

If you have the same fields appearing frequently in function signatures, you should probably make them an object.

https://refactoring.guru/fr/smells/data-clumps

kriss
  • 23,497
  • 17
  • 97
  • 116