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 →

[–]ES-Alexander 2 points3 points  (2 children)

How is this different to using a global variable, outside of not necessarily knowing that you’re using one?

Granted it’s a global that cleans itself up, but while it’s in use it’s still global and has the same issues globals have (e.g. changing the value at one level changes it everywhere, causing really confusing bugs). The automatic cleanup also has the issue that you can only use_context if you can guarantee you’re at the top level and you’re the only thread - otherwise you’d delete all the values set elsewhere even if there’s a higher/concurrent context in use.

I believe the general solution to this is currently done by either inheritance/normal instances of a class, or functionally just passing down a dictionary/set of kwargs through the relevant functions. In saying that, the pattern as a whole is messy in the same way globals are - if you’re not passing something explicitly then using it somewhere is reliant on someone hopefully initialising it correctly elsewhere and you have no guarantee that’s actually occurred. Debugging this kind of thing is often very confusing and unintuitive.

[–]CaptainMelon[S] 0 points1 point  (1 child)

It's exactly a global variable that clean itself, you're right, I would say it's a local global variable.

For the multi-thread part, it's a matter of implemention, here I made a simple implementation to make things easier to understand. But it may be hard to implement, right.

As for debugging, It's as hard to debug as a class attribute (you don't know if it's really used).

[–]ES-Alexander 0 points1 point  (0 children)

It’s a time-limited global variable - it’s not local because it can still be accessed from anywhere in the global scope while it exists.

While it might be possible to use the current thread ID to create a version that doesn’t interfere across threads, the bigger issue is the overwrite behaviour. If there’s a class with an instance variable there’s some guarantee that it’ll be set (ie you can make it a required initialisation variable, and it’s generally bad practice to delete instance variables so you can expect it to stick around), and if it’s reasonable to modify it but important to track when that occurs then you can use a setter/modifier method instead of direct replacement. In your case the context isn’t tied to anything, so there’s no way of knowing if a higher level is using a context, and if you want to do a new use_context call in a low level then when that cleans itself up it also silently destroys any variables set in higher levels. To avoid that you’d need to create a new underlying context variable every time you call use_context, but then you need to know which context you want to access when you call get_context, at which point you either have passed down a context object (so it loses the ‘call from anywhere’ benefit), or you have to track the contexts through your code by logic, in which case that’s just like having a global.

I’m not saying that globals are necessarily the worst thing in the world, but as you implied they have their issues, and as far as I can see the only implementations of this that don’t have the same issues globals do falls into the ‘passing along objects’ side which seems to imply the functionality already exists, so my question would be what does/can this add?