Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deleting your own variables #26

Closed
tukkek opened this issue Sep 3, 2017 · 3 comments
Closed

Deleting your own variables #26

tukkek opened this issue Sep 3, 2017 · 3 comments

Comments

@tukkek
Copy link

tukkek commented Sep 3, 2017

Found something new for you! So it turns out you can run this code:

def outer(x):
    del x
    return x

outer(1)

'''
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in outer
UnboundLocalError: local variable 'x' referenced before assignment
'''

Not sure you'll want to add it to the list because it's unlikely anyone would do that - but it is technically interesting in itself because as far as I know Python is the only language that will let you destroy a local variable (or even function argument!) instead of just letting it expire and be garbage-collected when the current context is destroyed (like when leaving the function or an "except" block). By mistyping, you could easily delete a variable that should, by all means, be there and be left with a "wtf just happened to my poor dear x?" T_T

Also keep in mind that this can create very confusing scenarios, especially since the __del__() special method can be implemented in any class. Think about this: you try to del x from inside your method - except that the actual __del__() function is never called - because it is not called when del is issued but when all reference counts are extinguished and the instance is garbage-collected. So if you pass x to a function as a parameter, it will still have (at least) one reference holding the instance in memory outside of the function itself!

I'll let you come up with a clever, fun code example to show this if you think that this is worthy of adding to the your list :)

@uranusjr
Copy link

uranusjr commented Sep 5, 2017

A more subtle example:

# foo.py

foo = 'foo'

def print_foo():
    print(foo)

del foo
>>> from foo import print_foo
>>> print_foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "foo.py", line 4, in print_foo
    print(foo)
NameError: name 'foo' is not defined

This is because variable capture happens on execution, not declaration. foo is deleted when the module is loaded (and all global code in it evaluated).

@satwikkansal
Copy link
Owner

satwikkansal commented Oct 11, 2017

I came up with an example to illustrate the fact that __del__ is not always called when del operator is encountered.

>>> class SomeClass():
...     def __del__(self):
...         print "Deleted"
... 
>>> x = SomeClass()
>>> y = x
>>> del x
>>> del y
Deleted

>>> x = SomeClass()
>>> y = x
>>> del x
>>> y
<__main__.SomeClass instance at 0x7f98a1a67fc8>
>>> del y # Notice that "__del__" is not called in this case because of the previous statement created an extra reference which still persists.
>>> globals() # Calling "globals" caused the existing reference to be destroyed and 
Deleted
{'__builtins__': <module '__builtin__' (built-in)>, 'SomeClass': <class __main__.SomeClass at 0x7f98a1a5f668>, '__package__': None, '__name__': '__main__', '__doc__': None}

Explanation: https://docs.python.org/3/reference/datamodel.html#object.__del__

Let me know your views guys :)

@satwikkansal
Copy link
Owner

Hey guys, I've added the example for now (sorry for the extreme delay). Feel free to suggest any changes and reopen the issue.

muscliary pushed a commit to muscliary/wtfpython that referenced this issue Sep 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants