+ 4

[Solved] Questions about default args, Python:

Trying to understand some stuff in a SO discussion. 1) When the interpreter reaches a func header for the 1st time and then jumps over the body to resume in global scope, we see that the func name gets added to the global namespace. We can say that func header is evaluated, right? 2) If yes, why can't I see the default argument also in gs? What can I do to see it before I actually call the function? (dir, vars etc didn't work) 3) Arguments passed are local to the func. But are default args also? 4) Why would a list keep changing when passed as default, if it were local to the function? (Is it something like a closure, in func object state) EDIT: Changed my mind and added the two other questions. The discussion I mentioned is at https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument?rq=1

21st Nov 2022, 4:29 AM
Korkunç el Gato
Korkunç el Gato - avatar
21 Antworten
+ 5
The default function arguments are not in global scope, they are stored against the function object. You can view them with inspect.signature I found out from this: https://stackoverflow.com/questions/12627118/get-a-function-arguments-default-value A function in python is not much different from a class. The main idea is, that the function header is evaluated only once. If you put a mutable object in the function header as default arg, then it's mutations would be tracked over the lifetime of the function object (not only a single invocation). Played around a bit: https://code.sololearn.com/cxSgXS2lP5Nw/?ref=app
21st Nov 2022, 5:16 AM
Tibor Santa
Tibor Santa - avatar
+ 6
Korkunç el Gato a good question! learned something new from you and Tibor Santa :)
21st Nov 2022, 7:10 AM
Sandeep
Sandeep - avatar
+ 5
Korkunç el Gato Tibor Santa Also, is this a good approach? (Defining a function, and calling another function in that function definition) Edit: (removed) I was confusing it with something else ,😅
21st Nov 2022, 8:49 AM
Sandeep
Sandeep - avatar
+ 5
Korkunç el Gato Tibor Santa thanks for the explanation. Tibor Santa, You are right! It is really important from functional programming point. I just wanted to check function declaration and another function invocation on the same line(on def keyword line). But as you said, it is not quite intuitive. I can do this and it will have no side effect: def add_d(a, b=4) -> (right?) Tibor Santa, Also i don't understand the 'importing' part. As default gets evaluated at function definition, I think this won't break anything even if we create d before importing (as the value we supplied at creation is local to the function) I am not very familiar with functional programming, please correct me if i am missing something ?
22nd Nov 2022, 6:54 AM
Sandeep
Sandeep - avatar
+ 4
Korkunç el Gato these are good questions, worthy of further research. Even the original SO article you linked, is very insightful.
21st Nov 2022, 5:21 AM
Tibor Santa
Tibor Santa - avatar
+ 4
Korkunç el Gato I cannot remember it correctly. Looks like i need to refresh my memory often. Can you give me the code link?
21st Nov 2022, 7:42 AM
Sandeep
Sandeep - avatar
+ 4
Korkunç el Gato i tried to find it but no luck 😅
21st Nov 2022, 7:44 AM
Sandeep
Sandeep - avatar
+ 4
Korkunç el Gato yes it was an amazing thread 😺 Are you talking about something like this: https://code.sololearn.com/ca8SuyH4fsnG/?ref=app Here add_d args gets evaluated when they are defined.
21st Nov 2022, 8:38 AM
Sandeep
Sandeep - avatar
+ 4
Sandeep In your example: d = "4" def add_d(a, b=int(d)): You would lift a global value (d) into the scope of a function. As an advocate of functional programming, I prefer to use pure functions, for which it is important that they cannot depend on external (global) state. Even though this expression is only evaluated once, and the result ends up being an immutable (constant) value... I still think that it is not really intuitive in terms of the control flow. And if this function is located in a library or external file, it matters a lot, at which point in your code you pull in this file with import, and whether you change the value of d before that. In a bigger code this behaviour can be a source of bugs that is extremely difficult to find.
21st Nov 2022, 7:00 PM
Tibor Santa
Tibor Santa - avatar
+ 3
Oh. print(func.__defaults__) right there before the calls. Dang. I think I got it. Had I read everything in dir(func) then I would see " __defaults__" :/ 🦇 forever indeed. Dear mentors upvoted it so I am keeping this even if I answered myself, if that's ok
21st Nov 2022, 5:16 AM
Korkunç el Gato
Korkunç el Gato - avatar
+ 3
at Tibor Santa: lol I thought I was gonna die alone, thank you :-) edit: my problem was that locals get destroyed once executed and it was not in globals so where was it hehe thank you for the clear explanation
21st Nov 2022, 5:18 AM
Korkunç el Gato
Korkunç el Gato - avatar
+ 3
Tibor Santa Ok, I sent a reply myself about the same time you did, thinking there was no answer, so I'm definitely keeping this now. Cool to know you liked the SO link.
21st Nov 2022, 5:25 AM
Korkunç el Gato
Korkunç el Gato - avatar
+ 3
Sandeep Cool :-) Do you remember the time Noteve was around, I think one of his codes was showcasing this . I had no idea the concept had more to do with this acting like a class , with the function object and all, we'd just focused on list mutability IIRC and very lightly on scope. Now the loose ends are tied together I guess.
21st Nov 2022, 7:21 AM
Korkunç el Gato
Korkunç el Gato - avatar
+ 3
Korkunç el Gato I have a firm belief that functional paradigm is beneficial and useful to apply, even in case of more traditional situations, mainstream OOP languages. If you can ensure, that a function behaves exactly the same way, regardless of external condition, and you are able to write the majority of the code this way, then it is trivial to test, you can exclude a lot of potential bugs and make the code easy to parallelize, making it much faster. This is recognized by modern language designers who add such features to old languages, like streams or records in Java, concept of 'immutability by default' in Kotlin... But languages which are functional by design, such as Haskell or Clojure, can reap the biggest benefit. Python is a dynamic language by design. It was built this way to make it easy and effortless to use. But safety and maintainability were not the primary design principles. "The Dutch" refers to Guido van Rossum, the language creator and BDFL.
21st Nov 2022, 9:05 PM
Tibor Santa
Tibor Santa - avatar
+ 3
Korkunç el Gato in my opinion using globals is an antipattern which can be very easily avoided. Just pass the required value explicitly as a function argument, problem solved.
21st Nov 2022, 9:12 PM
Tibor Santa
Tibor Santa - avatar
+ 2
Sandeep Just going by the description in your last post, I think I got the same impression at first: While you might mean all kinds of inner functions, the ones that you use as closure factory with their enclosing scope actually do keep the free variable from the enclosing scope in a similar way the default argument here is kept, because the enclosing function returns the inner function object(no call). If you assign the enclosing func call to a global variable outside, it's like a photo of the inner func, without the argument yet, but with the free variable existing as some sort of class member itself, and then you pass the argument to this new global variable and inner func returns a value. Like a class and its instance. I think that is why they seem to deem closures part of OOP and kind of mimicing classes. I have to study that further but that's what I've gathered this far. def enc(): x = 5 def loc(a): return x * a #edit not 5 but x return loc globvar = enc() print(globvar(3))
21st Nov 2022, 6:56 PM
Korkunç el Gato
Korkunç el Gato - avatar
+ 2
Tibor Santa This is a bit tangential, but is there any use case where using the global variable in an enclosing or local scope would become the only logical, efficient thing to do, if you were to speak from experience and observation? In the link from SO for example, while admitting that it's not best practice to use mutables as default args, some said "the Dutch" understand what this is and use this to their advantage. Over time I got this idea that you're into functional programming, is that because of what you just wrote here about?
21st Nov 2022, 8:28 PM
Korkunç el Gato
Korkunç el Gato - avatar
+ 2
Tibor Santa I thought they were referring to anyone who is nearly as much an expert on Python as GVR because some of them were also referring to themselves when saying that😁 Well from here you're all wizards. One would still have to have a good grasp of OOP to become a better functional programmer, I take it, so it's further down the path for us intermediates. But at least Python is said to be multiparadigm so keeping our eyes open as learners and starting to modularize our codes would be a good start I guess, so that we can internalize more of what you say later.
21st Nov 2022, 9:17 PM
Korkunç el Gato
Korkunç el Gato - avatar
+ 2
Tibor Santa Thanks for specifically addressing the other question too. It does help me understand what I need to make a priority.
21st Nov 2022, 9:24 PM
Korkunç el Gato
Korkunç el Gato - avatar
+ 1
Sandeep Oh yeah I couldn't either lol it's his endless list code I've confused with Oma Falk's discussion "what's wrong with my code" The dictionary with the default argument, Tibor Santa was there too and made the explanation 😊 It's when the argument gets evaluated that was partly discussed there. I'll definitely reread that. (Oma's dict's get had done something weird in the second arg, mutability was also relevant I suppose, good reason for me to revisit that!) Sorry btw :-) https://www.sololearn.com/Discuss/3056375/?ref=app (all arguments getting evaluated before call is discussed there: with defaults it's evaluated before and changes func object as class "member" sort of thing, I hope I'm not mixing them up, seems they are close concepts)
21st Nov 2022, 8:08 AM
Korkunç el Gato
Korkunç el Gato - avatar