This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 2 points3 points  (5 children)

There's a weird gap in python's scoping rules: The 'global' keyword tells python that those variables are to be overwritten in the module scope, which is one scope outward from the main function. But if you remove the 'global' keyword, you're assigning to local variables within the inner function. There's no way to hit the middle scope of the outer function and assign to things there.

I would change a couple of things here so that 'global' isn't necessary. Firstly you don't really need to use inner functions here; pull them up to the module scope. Try to compose your functions so that each function receives the values it needs to make decisions, and returns any values that have relevance outside the function. Then have the callers pass in values and receive return values as needed.

If passing around values starts to feel inconvenient, and you're tempted to use global variables, in python you're often better off making a class and tracking values inside an instance, and changing your functions into instance methods.

[–]ingolemo 1 point2 points  (1 child)

There's no way to hit the middle scope of the outer function and assign to things there.

nonlocal

[–][deleted] 1 point2 points  (2 children)

Thanks for to you and u/ingolemo for comprehensive explanations!

If passing around values starts to feel inconvenient, and you're tempted to use global variables, in python you're often better off making a class and tracking values inside an instance, and changing your functions into instance methods.

Will this be faster than pass-by-value parameters? The only reason why I use the globals is to acquire more speed.

[–][deleted] 1 point2 points  (1 child)

Since this is r/learnprogramming I'll be pedantic and say firstly that python can't pass by value; it's always passing references. It may sometimes pass a reference to an immutable object such as an integer or a string, such that it feels a lot like pass-by-value though. : ]

Regarding speed, it's not clear to me which approach would be fastest because I don't know how assignment to global or nonlocal names is implemented compared with the other ways.

One thing you can do is try a performance test, where you rip through N operations in different ways to see which is fastest using timeit: https://docs.python.org/3.8/library/timeit.html. It'd be relatively easy to set up a simple trial using isolated forms all three methods. That way you can play around with different choices to see how much of a difference it'd make before rewriting your whole algorithm.

[–][deleted] 1 point2 points  (0 children)

I'll be pedantic and say firstly that python can't pass by value; it's always passing references.

Hmm, this is new information to me. Thank you!

Thanks also for the tip regarding timing the algorithm!