Related
I can't really think of any reason why Python needs the del keyword (and most languages seem to not have a similar keyword). For instance, rather than deleting a variable, one could just assign None to it. And when deleting from a dictionary, a del method could be added.
Is there a reason to keep del in Python, or is it a vestige of Python's pre-garbage collection days?
Firstly, you can del other things besides local variables
del list_item[4]
del dictionary["alpha"]
Both of which should be clearly useful. Secondly, using del on a local variable makes the intent clearer. Compare:
del foo
to
foo = None
I know in the case of del foo that the intent is to remove the variable from scope. It's not clear that foo = None is doing that. If somebody just assigned foo = None I might think it was dead code. But I instantly know what somebody who codes del foo was trying to do.
There's this part of what del does (from the Python Language Reference):
Deletion of a name removes the binding of that name from the local or global namespace
Assigning None to a name does not remove the binding of the name from the namespace.
(I suppose there could be some debate about whether removing a name binding is actually useful, but that's another question.)
One place I've found del useful is cleaning up extraneous variables in for loops:
for x in some_list:
do(x)
del x
Now you can be sure that x will be undefined if you use it outside the for loop.
Deleting a variable is different than setting it to None
Deleting variable names with del is probably something used rarely, but it is something that could not trivially be achieved without a keyword. If you can create a variable name by writing a=1, it is nice that you can theoretically undo this by deleting a.
It can make debugging easier in some cases as trying to access a deleted variable will raise an NameError.
You can delete class instance attributes
Python lets you write something like:
class A(object):
def set_a(self, a):
self.a=a
a=A()
a.set_a(3)
if hasattr(a, "a"):
print("Hallo")
If you choose to dynamically add attributes to a class instance, you certainly want to be able to undo it by writing
del a.a
There is a specific example of when you should use del (there may be others, but I know about this one off hand) when you are using sys.exc_info() to inspect an exception. This function returns a tuple, the type of exception that was raised, the message, and a traceback.
The first two values are usually sufficient to diagnose an error and act on it, but the third contains the entire call stack between where the exception was raised and where the the exception is caught. In particular, if you do something like
try:
do_evil()
except:
exc_type, exc_value, tb = sys.exc_info()
if something(exc_value):
raise
the traceback, tb ends up in the locals of the call stack, creating a circular reference that cannot be garbage collected. Thus, it is important to do:
try:
do_evil()
except:
exc_type, exc_value, tb = sys.exc_info()
del tb
if something(exc_value):
raise
to break the circular reference. In many cases where you would want to call sys.exc_info(), like with metaclass magic, the traceback is useful, so you have to make sure that you clean it up before you can possibly leave the exception handler. If you don't need the traceback, you should delete it immediately, or just do:
exc_type, exc_value = sys.exc_info()[:2]
To avoid it all together.
Just another thinking.
When debugging http applications in framework like Django, the call stack full of useless and messed up variables previously used, especially when it's a very long list, could be very painful for developers. so, at this point, namespace controlling could be useful.
Using "del" explicitly is also better practice than assigning a variable to None. If you attempt to del a variable that doesn't exist, you'll get a runtime error but if you attempt to set a variable that doesn't exist to None, Python will silently set a new variable to None, leaving the variable you wanted deleted where it was. So del will help you catch your mistakes earlier
del is often seen in __init__.py files. Any global variable that is defined in an __init__.py file is automatically "exported" (it will be included in a from module import *). One way to avoid this is to define __all__, but this can get messy and not everyone uses it.
For example, if you had code in __init__.py like
import sys
if sys.version_info < (3,):
print("Python 2 not supported")
Then your module would export the sys name. You should instead write
import sys
if sys.version_info < (3,):
print("Python 2 not supported")
del sys
To add a few points to above answers:
del x
Definition of x indicates r -> o (a reference r pointing to an object o) but del x changes r rather than o. It is an operation on the reference (pointer) to object rather than the object associated with x. Distinguishing between r and o is key here.
It removes it from locals().
Removes it from globals() if x belongs there.
Removes it from the stack frame (removes the reference physically from it, but the object itself resides in object pool and not in the stack frame).
Removes it from the current scope. It is very useful to limit the span of definition of a local variable, which otherwise can cause problems.
It is more about declaration of the name rather than definition of content.
It affects where x belongs to, not where x points to. The only physical change in memory is this. For example if x is in a dictionary or list, it (as a reference) is removed from there(and not necessarily from the object pool). In this example, the dictionary it belongs is the stack frame (locals()), which overlaps with globals().
I've found del to be useful for pseudo-manual memory management when handling large data with Numpy. For example:
for image_name in large_image_set:
large_image = io.imread(image_name)
height, width, depth = large_image.shape
large_mask = np.all(large_image == <some_condition>)
# Clear memory, make space
del large_image; gc.collect()
large_processed_image = np.zeros((height, width, depth))
large_processed_image[large_mask] = (new_value)
io.imsave("processed_image.png", large_processed_image)
# Clear memory, make space
del large_mask, large_processed_image; gc.collect()
This can be the difference between bringing a script to a grinding halt as the system swaps like mad when the Python GC can't keep up, and it running perfectly smooth below a loose memory threshold that leaves plenty of headroom to use the machine to browse and code while it's working.
Force closing a file after using numpy.load:
A niche usage perhaps but I found it useful when using numpy.load to read a file. Every once in a while I would update the file and need to copy a file with the same name to the directory.
I used del to release the file and allow me to copy in the new file.
Note I want to avoid the with context manager as I was playing around with plots on the command line and didn't want to be pressing tab a lot!
See this question.
I would like to elaborate on the accepted answer to highlight the nuance between setting a variable to None versus removing it with del:
Given the variable foo = 'bar', and the following function definition:
def test_var(var):
if var:
print('variable tested true')
else:
print('variable tested false')
Once initially declared, test_var(foo) yields variable tested true as expected.
Now try:
foo = None
test_var(foo)
which yields variable tested false.
Contrast this behavior with:
del foo
test_var(foo)
which now raises NameError: name 'foo' is not defined.
As an example of what del can be used for, I find it useful i situations like this:
def f(a, b, c=3):
return '{} {} {}'.format(a, b, c)
def g(**kwargs):
if 'c' in kwargs and kwargs['c'] is None:
del kwargs['c']
return f(**kwargs)
# g(a=1, b=2, c=None) === '1 2 3'
# g(a=1, b=2) === '1 2 3'
# g(a=1, b=2, c=4) === '1 2 4'
These two functions can be in different packages/modules and the programmer doesn't need to know what default value argument c in f actually have. So by using kwargs in combination with del you can say "I want the default value on c" by setting it to None (or in this case also leave it).
You could do the same thing with something like:
def g(a, b, c=None):
kwargs = {'a': a,
'b': b}
if c is not None:
kwargs['c'] = c
return f(**kwargs)
However I find the previous example more DRY and elegant.
When is del useful in python?
You can use it to remove a single element of an array instead of the slice syntax x[i:i+1]=[]. This may be useful if for example you are in os.walk and wish to delete an element in the directory. I would not consider a keyword useful for this though, since one could just make a [].remove(index) method (the .remove method is actually search-and-remove-first-instance-of-value).
I think one of the reasons that del has its own syntax is that replacing it with a function might be hard in certain cases given it operates on the binding or variable and not the value it references. Thus if a function version of del were to be created a context would need to be passed in. del foo would need to become globals().remove('foo') or locals().remove('foo') which gets messy and less readable. Still I say getting rid of del would be good given its seemingly rare use. But removing language features/flaws can be painful. Maybe python 4 will remove it :)
The "del" command is very useful for controlling data in an array, for example:
elements = ["A", "B", "C", "D"]
# Remove first element.
del elements[:1]
print(elements)
Output:
['B', 'C', 'D']
del deletes the binding of the variable and its object that it points to.
>>> a = ['a', 'b', 'c']
>>> b = a
>>> del a
>>> b
['a', 'b', 'c']
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
A simple use case I can think of would be in case you have used a built-in function name as a variable, and you want to use that function after it has been already "overridden" by your variable name.
t = ('a', "letter")
value, type = t
print(value, type)
del type
print(type(value))
Output:
a letter
<class 'str'>
Yet another niche usage:
In pyroot with ROOT5 or ROOT6, "del" may be useful to remove a python object that referred to a no-longer existing C++ object. This allows the dynamic lookup of pyroot to find an identically-named C++ object and bind it to the python name. So you can have a scenario such as:
import ROOT as R
input_file = R.TFile('inputs/___my_file_name___.root')
tree = input_file.Get('r')
tree.Draw('hy>>hh(10,0,5)')
R.gPad.Close()
R.hy # shows that hy is still available. It can even be redrawn at this stage.
tree.Draw('hy>>hh(3,0,3)') # overwrites the C++ object in ROOT's namespace
R.hy # shows that R.hy is None, since the C++ object it pointed to is gone
del R.hy
R.hy # now finds the new C++ object
Hopefully, this niche will be closed with ROOT7's saner object management.
del is removing the variable from the current scope unless it is re-initialized. Setting it to None keeps it in the current scope.
a = "python string"
print(a)
del a
print(a)
a = "new python string"
print(a)
Output:
python string
Traceback (most recent call last):
File "testing.py", line 4, in <module>
print(a)
NameError: name 'a' is not defined
As I have not seen a interactive console answer, I'll be showing one.
When foo=None that reference and the object exist, it's not pointing to it.
While del foo destroys the object and reference too.
So if you do something like this if foo is None and it was deleted it will rise NameError as the the reference, it's object and everything in between was deleted with del
Deletion of a target list recursively deletes each target, from left to right.
Meanwhile foo=None is just a reference pointing to None so the reference is still kicking, same for the object.
[...]In Python, variables are references to objects and any variable can reference any object[...]
Link to quote 1
Link to quote 2
Another niche case, but useful.
from getpass import getpass
pass = getpass()
token = get_auth_token(pass)
del pass
# Assume more code here...
After the deletion of the pass variable, you don't run the risk of it being printed out later by mistake, or otherwise ending up in a log or stack trace.
Here goes my 2 cents contribution:
I have a optimization problem where I use a Nlopt library for it.
I initializing the class and some of its methods, I was using in several other parts of the code.
I was having ramdom results even if applying the same numerical problem.
I just realized that by doing it, some spurius data was contained in the object when it should have no issues at all. After using del, I guess the memory is being properly cleared and it might be an internal issue to that class where some variables might not be liking to be reused without proper constructor.
Once I had to use:
del serial
serial = None
because using only:
serial = None
didn't release the serial port fast enough to immediately open it again.
From that lesson I learned that del really meant: "GC this NOW! and wait until it's done" and that is really useful in a lot of situations. Of course, you may have a system.gc.del_this_and_wait_balbalbalba(obj).
del is the equivalent of "unset" in many languages
and as a cross reference point moving from another language to python..
people tend to look for commands that do the same thing that they used to do in their first language...
also
setting a var to "" or none doesn't really remove the var from scope..it just empties its value
the name of the var itself would still be stored in memory...why?!?
in a memory intensive script..keeping trash behind its just a no no
and anyways...every language out there has some form of an "unset/delete" var function..why not python?
In my program I create an un-ending amount of class instances. the amount depends on how long the program is running. However I don't need the instances at all after a certain code being run. How could i remove them completely from memory?
Simple example code:
class Player:
def __init__(self, color):
self.color = color
for n in range(1000):
p = Player('black')
Would del p in this case completely remove that instance?
Python will remove them from memory for you when they are no longer referred to. If you have Player instances that refer to other Player instances (ex: p.teammates = [list of Players]) you could end up with circular references that may prevent them from being garbage collected. In this case you should consider the weakref module.
for example:
>>>sam = Player('blue')
>>>rob = Player('green')
>>>sam.team = [sam, rob]
>>>rob.team = [sam, rob]
>>> #sam and rob may not be deleted because they contain
>>> #references to eachother so the reference count cannot reach 0
>>>del sam #del is a way to manually dereference an object in an interactive prompt. Otherwise the interpreter cannot know you won't use it again unlike when the entire code is known at the beginning.
>>>print(rob.team[0].color) #this prints 'blue' proving that sam hasn't been deleted yet
blue
so how do we fix it?
>>>sam = Player('blue')
>>>rob = Player('green')
>>>sam.team = [weakref.ref(sam), weakref.ref(rob)]
>>>rob.team = [weakref.ref(sam), weakref.ref(rob)]
>>> #now sam and rob can be deleted, but we've changed the contents of `p.team` a bit:
>>> #if they both still exist:
>>>rob.team[0]() is sam #calling a `ref` object returns the object it refers to if it still exists
True
>>>del sam
>>>rob.team[0]() #calling a `ref` object that has been deleted returns `None`
None
>>>rob.team[0]().color #sam no longer exists so we can't get his color
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'color'
In this instance, del p would only remove the reference to the Player object, so that it can later be picked up by the garbage collector.
However, this also happens when it goes out-of-scope.
In most everyday Python, there is no need to use explicit del statements.
There is no way in Python to delete an instance. Instead you can delete references to the instance, and once they are all gone, the object is reclaimed.
In C++, you can do this to force local scope:
{
int i = 1;
// Do stuff
}
// local variable i is destroyed
{
int i = 7;
// Do more stuff
}
This has the benefit that by the end of a forced local scope, any variables declared in the bracket are gone. This can help prevent using a previously defined variable x in a place later on where you didn't intend to use x.
Can you do this in Python? If so, how?
==UPDATE==
I'm aware of functions - which is the obvious thing. I was wondering if there was a quick way to do the above when the code is simple and not worth creating separate a function for - just some quick notation to emphasize that the variables in this block are not to be used anywhere else in the function.
From what people have said so far the short answer is no.
(I understand that there are clever ways like "del", or that this desire to have blocks may suggest refactoring into a separate function anyway. However I would like to emphasize this is just for short snippets where you want to emphasize the variables in this small block are not to be used elsewhere.)
In Python, if you declare a variable inside a function, it is local and cannot be accessed outside the function
>>> def x():
i = 5
>>> x()
>>> i
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
i
NameError: name 'i' is not defined
>>>
Alternatively, you can delete the variable from the namespace at the end so that you cannot reuse it.
>>> i = 5
>>> del i
>>> i
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
i
NameError: name 'i' is not defined
>>>
I had this same question, and found out that you absolutely can!
It's not as clean as the c style blocks, but through two quirks of python we can make it serve our purposes.
The Quirks:
Whatever code is inside a class runs immediately, even if the class is never used.
You can reuse the name of a class as many times as you want.
Here's your example:
class DoStuff:
i = 1
# Do stuff
# local variable i is destroyed
class DoStuff:
i = 7
# Do more stuff
# local variable i is destroyed
To fully represent the flexibility here, see this example. I've named the class "Scope", because that's probably what I'd call it to differentiate from other named classes.
Note that "Scope" can of course be anything.
I'd recommend you stick with one name for the entire project and add that name to your documentation, so that there is an understanding that this is a special name that should never ever be instantiated.
outer = 1
class Scope:
inner = outer
print("runs first ---")
print("outer %d" % outer)
print("inner %d" % inner)
class Scope:
inner = outer + 1
print("runs second ---")
print("outer %d" % outer)
print("inner %d" % inner)
print("runs last ---")
print("outer %d" % outer)
print("inner %d" % inner) # This will give an error. Inner does not exist in this scope!
Output:
runs first ---
outer 1
inner 1
runs second ---
outer 1
inner 2
runs last ---
outer 1
Traceback (most recent call last):
File "test.py", line 18, in <module>
print("inner %d" % inner) # This will give an error. Inner does not exist in this scope!
NameError: name 'inner' is not defined
So it is doable - let's take a look at the benefits / downsides tradeoffs.
Benefits:
Code remains linear and no unnecessary leaps in logic are needed to follow the code flow. This linearity will make it easier for newcomers to read and understand what a section of code actually does.
Code is self-documenting to future coders that this code is only used in this one place, making it easier to edit, as the coder will not need to do an unnecessary search to find other instances.
Downsides:
We're using quirks of Python to make this work, and I sense that this very idea of limiting scope as opposed to creating new one-time-use functions is not something that Python programmers tend to do. This may cause tensions in the workplace, or result in complaints of using a hack as opposed to following conventions on creating small functions whether or not something is used more than once.
If you leave the project and new programmers come onboard and see this code, they will probably be confused initially. Some documentation will be needed in order to set expectations, and care must be taken to make sure the explanation in the documentation remains accurate.
I think this is a worthwhile effort for all code where you'd like to limit the scope but there are not multiple places this code is used, or it is not yet clear how to write a generic function to address all those situations.
If anyone reading this feels there are other tradeoffs, comment here and I'll make sure they're represented in the "Downsides" section.
Here's some more discussion around this convention, which has been preferred by John Carmack, Jonathan Blow, and Casey Muratori.
https://news.ycombinator.com/item?id=12120752
I have committed to solve this with trickery.
from scoping import scoping
a = 2
with scoping():
assert(2 == a)
a = 3
b = 4
scoping.keep('b')
assert(3 == a)
assert(2 == a)
assert(4 == b)
https://github.com/l74d/scoping
By the way, I found that the dummy class solution might result in memory leak. For example, large numpy arrays created in the overwritten class did not seem to be garbage collected by watching the memory statistics, which may be an implementation-dependent thing though.
If you don't like the del solution, you can nest function definitions:
def one_function():
x=0
def f():
x = 1
f()
print(x) # 0
Of course, I think the better approach is to just split things up into smaller functions, so there's no need for this manual scoping. In C++, the coolest thing about it is that the destructor is automatically called -- in Python, you can't really guarantee that the destructor will be called, so this scoping wouldn't be very useful even if it were possible.
In C++, you use local scope with brackets {} to avoid variable redefinitions or naming conflicts:
{
int var=3;
}
{
float var=1.0f;
}
While in python, there are no explicit variable definition , you just assign some objects to a var name when you want to use it, and rebind the same name to some new variable:
var=3
#do something
var=1.0 #no need to "del var", var refers to a float object now
#do more stuff
Note that the use of scope block in C++ might be indicating your code needs to be refactored to functions or methods, which can be named and reused. And it's the same with python.
I can't really think of any reason why Python needs the del keyword (and most languages seem to not have a similar keyword). For instance, rather than deleting a variable, one could just assign None to it. And when deleting from a dictionary, a del method could be added.
Is there a reason to keep del in Python, or is it a vestige of Python's pre-garbage collection days?
Firstly, you can del other things besides local variables
del list_item[4]
del dictionary["alpha"]
Both of which should be clearly useful. Secondly, using del on a local variable makes the intent clearer. Compare:
del foo
to
foo = None
I know in the case of del foo that the intent is to remove the variable from scope. It's not clear that foo = None is doing that. If somebody just assigned foo = None I might think it was dead code. But I instantly know what somebody who codes del foo was trying to do.
There's this part of what del does (from the Python Language Reference):
Deletion of a name removes the binding of that name from the local or global namespace
Assigning None to a name does not remove the binding of the name from the namespace.
(I suppose there could be some debate about whether removing a name binding is actually useful, but that's another question.)
One place I've found del useful is cleaning up extraneous variables in for loops:
for x in some_list:
do(x)
del x
Now you can be sure that x will be undefined if you use it outside the for loop.
Deleting a variable is different than setting it to None
Deleting variable names with del is probably something used rarely, but it is something that could not trivially be achieved without a keyword. If you can create a variable name by writing a=1, it is nice that you can theoretically undo this by deleting a.
It can make debugging easier in some cases as trying to access a deleted variable will raise an NameError.
You can delete class instance attributes
Python lets you write something like:
class A(object):
def set_a(self, a):
self.a=a
a=A()
a.set_a(3)
if hasattr(a, "a"):
print("Hallo")
If you choose to dynamically add attributes to a class instance, you certainly want to be able to undo it by writing
del a.a
There is a specific example of when you should use del (there may be others, but I know about this one off hand) when you are using sys.exc_info() to inspect an exception. This function returns a tuple, the type of exception that was raised, the message, and a traceback.
The first two values are usually sufficient to diagnose an error and act on it, but the third contains the entire call stack between where the exception was raised and where the the exception is caught. In particular, if you do something like
try:
do_evil()
except:
exc_type, exc_value, tb = sys.exc_info()
if something(exc_value):
raise
the traceback, tb ends up in the locals of the call stack, creating a circular reference that cannot be garbage collected. Thus, it is important to do:
try:
do_evil()
except:
exc_type, exc_value, tb = sys.exc_info()
del tb
if something(exc_value):
raise
to break the circular reference. In many cases where you would want to call sys.exc_info(), like with metaclass magic, the traceback is useful, so you have to make sure that you clean it up before you can possibly leave the exception handler. If you don't need the traceback, you should delete it immediately, or just do:
exc_type, exc_value = sys.exc_info()[:2]
To avoid it all together.
Just another thinking.
When debugging http applications in framework like Django, the call stack full of useless and messed up variables previously used, especially when it's a very long list, could be very painful for developers. so, at this point, namespace controlling could be useful.
Using "del" explicitly is also better practice than assigning a variable to None. If you attempt to del a variable that doesn't exist, you'll get a runtime error but if you attempt to set a variable that doesn't exist to None, Python will silently set a new variable to None, leaving the variable you wanted deleted where it was. So del will help you catch your mistakes earlier
del is often seen in __init__.py files. Any global variable that is defined in an __init__.py file is automatically "exported" (it will be included in a from module import *). One way to avoid this is to define __all__, but this can get messy and not everyone uses it.
For example, if you had code in __init__.py like
import sys
if sys.version_info < (3,):
print("Python 2 not supported")
Then your module would export the sys name. You should instead write
import sys
if sys.version_info < (3,):
print("Python 2 not supported")
del sys
To add a few points to above answers:
del x
Definition of x indicates r -> o (a reference r pointing to an object o) but del x changes r rather than o. It is an operation on the reference (pointer) to object rather than the object associated with x. Distinguishing between r and o is key here.
It removes it from locals().
Removes it from globals() if x belongs there.
Removes it from the stack frame (removes the reference physically from it, but the object itself resides in object pool and not in the stack frame).
Removes it from the current scope. It is very useful to limit the span of definition of a local variable, which otherwise can cause problems.
It is more about declaration of the name rather than definition of content.
It affects where x belongs to, not where x points to. The only physical change in memory is this. For example if x is in a dictionary or list, it (as a reference) is removed from there(and not necessarily from the object pool). In this example, the dictionary it belongs is the stack frame (locals()), which overlaps with globals().
I've found del to be useful for pseudo-manual memory management when handling large data with Numpy. For example:
for image_name in large_image_set:
large_image = io.imread(image_name)
height, width, depth = large_image.shape
large_mask = np.all(large_image == <some_condition>)
# Clear memory, make space
del large_image; gc.collect()
large_processed_image = np.zeros((height, width, depth))
large_processed_image[large_mask] = (new_value)
io.imsave("processed_image.png", large_processed_image)
# Clear memory, make space
del large_mask, large_processed_image; gc.collect()
This can be the difference between bringing a script to a grinding halt as the system swaps like mad when the Python GC can't keep up, and it running perfectly smooth below a loose memory threshold that leaves plenty of headroom to use the machine to browse and code while it's working.
Force closing a file after using numpy.load:
A niche usage perhaps but I found it useful when using numpy.load to read a file. Every once in a while I would update the file and need to copy a file with the same name to the directory.
I used del to release the file and allow me to copy in the new file.
Note I want to avoid the with context manager as I was playing around with plots on the command line and didn't want to be pressing tab a lot!
See this question.
I would like to elaborate on the accepted answer to highlight the nuance between setting a variable to None versus removing it with del:
Given the variable foo = 'bar', and the following function definition:
def test_var(var):
if var:
print('variable tested true')
else:
print('variable tested false')
Once initially declared, test_var(foo) yields variable tested true as expected.
Now try:
foo = None
test_var(foo)
which yields variable tested false.
Contrast this behavior with:
del foo
test_var(foo)
which now raises NameError: name 'foo' is not defined.
As an example of what del can be used for, I find it useful i situations like this:
def f(a, b, c=3):
return '{} {} {}'.format(a, b, c)
def g(**kwargs):
if 'c' in kwargs and kwargs['c'] is None:
del kwargs['c']
return f(**kwargs)
# g(a=1, b=2, c=None) === '1 2 3'
# g(a=1, b=2) === '1 2 3'
# g(a=1, b=2, c=4) === '1 2 4'
These two functions can be in different packages/modules and the programmer doesn't need to know what default value argument c in f actually have. So by using kwargs in combination with del you can say "I want the default value on c" by setting it to None (or in this case also leave it).
You could do the same thing with something like:
def g(a, b, c=None):
kwargs = {'a': a,
'b': b}
if c is not None:
kwargs['c'] = c
return f(**kwargs)
However I find the previous example more DRY and elegant.
When is del useful in python?
You can use it to remove a single element of an array instead of the slice syntax x[i:i+1]=[]. This may be useful if for example you are in os.walk and wish to delete an element in the directory. I would not consider a keyword useful for this though, since one could just make a [].remove(index) method (the .remove method is actually search-and-remove-first-instance-of-value).
I think one of the reasons that del has its own syntax is that replacing it with a function might be hard in certain cases given it operates on the binding or variable and not the value it references. Thus if a function version of del were to be created a context would need to be passed in. del foo would need to become globals().remove('foo') or locals().remove('foo') which gets messy and less readable. Still I say getting rid of del would be good given its seemingly rare use. But removing language features/flaws can be painful. Maybe python 4 will remove it :)
The "del" command is very useful for controlling data in an array, for example:
elements = ["A", "B", "C", "D"]
# Remove first element.
del elements[:1]
print(elements)
Output:
['B', 'C', 'D']
del deletes the binding of the variable and its object that it points to.
>>> a = ['a', 'b', 'c']
>>> b = a
>>> del a
>>> b
['a', 'b', 'c']
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
A simple use case I can think of would be in case you have used a built-in function name as a variable, and you want to use that function after it has been already "overridden" by your variable name.
t = ('a', "letter")
value, type = t
print(value, type)
del type
print(type(value))
Output:
a letter
<class 'str'>
Yet another niche usage:
In pyroot with ROOT5 or ROOT6, "del" may be useful to remove a python object that referred to a no-longer existing C++ object. This allows the dynamic lookup of pyroot to find an identically-named C++ object and bind it to the python name. So you can have a scenario such as:
import ROOT as R
input_file = R.TFile('inputs/___my_file_name___.root')
tree = input_file.Get('r')
tree.Draw('hy>>hh(10,0,5)')
R.gPad.Close()
R.hy # shows that hy is still available. It can even be redrawn at this stage.
tree.Draw('hy>>hh(3,0,3)') # overwrites the C++ object in ROOT's namespace
R.hy # shows that R.hy is None, since the C++ object it pointed to is gone
del R.hy
R.hy # now finds the new C++ object
Hopefully, this niche will be closed with ROOT7's saner object management.
del is removing the variable from the current scope unless it is re-initialized. Setting it to None keeps it in the current scope.
a = "python string"
print(a)
del a
print(a)
a = "new python string"
print(a)
Output:
python string
Traceback (most recent call last):
File "testing.py", line 4, in <module>
print(a)
NameError: name 'a' is not defined
As I have not seen a interactive console answer, I'll be showing one.
When foo=None that reference and the object exist, it's not pointing to it.
While del foo destroys the object and reference too.
So if you do something like this if foo is None and it was deleted it will rise NameError as the the reference, it's object and everything in between was deleted with del
Deletion of a target list recursively deletes each target, from left to right.
Meanwhile foo=None is just a reference pointing to None so the reference is still kicking, same for the object.
[...]In Python, variables are references to objects and any variable can reference any object[...]
Link to quote 1
Link to quote 2
Another niche case, but useful.
from getpass import getpass
pass = getpass()
token = get_auth_token(pass)
del pass
# Assume more code here...
After the deletion of the pass variable, you don't run the risk of it being printed out later by mistake, or otherwise ending up in a log or stack trace.
Here goes my 2 cents contribution:
I have a optimization problem where I use a Nlopt library for it.
I initializing the class and some of its methods, I was using in several other parts of the code.
I was having ramdom results even if applying the same numerical problem.
I just realized that by doing it, some spurius data was contained in the object when it should have no issues at all. After using del, I guess the memory is being properly cleared and it might be an internal issue to that class where some variables might not be liking to be reused without proper constructor.
Once I had to use:
del serial
serial = None
because using only:
serial = None
didn't release the serial port fast enough to immediately open it again.
From that lesson I learned that del really meant: "GC this NOW! and wait until it's done" and that is really useful in a lot of situations. Of course, you may have a system.gc.del_this_and_wait_balbalbalba(obj).
del is the equivalent of "unset" in many languages
and as a cross reference point moving from another language to python..
people tend to look for commands that do the same thing that they used to do in their first language...
also
setting a var to "" or none doesn't really remove the var from scope..it just empties its value
the name of the var itself would still be stored in memory...why?!?
in a memory intensive script..keeping trash behind its just a no no
and anyways...every language out there has some form of an "unset/delete" var function..why not python?
There are several threads on Python garbage collection in SO, and after reading about five, plus some doc on line, i am still not sure as to how garbage collection works and how i should manage objects which i am not using. In fact somewhere i read one should not do anything about collecting garbage, others tell one should del objects, while others again explain de-referencing an object is enough for Python to collect it as garbage.
So, at the risk of creating a duplicate, i will ask the question again, but differently, hoping to get more comprehensive and clearer information.
In my case i want to make a small simulation with objects representing people. Several instances of the Person() class will be created. It should exist for some time until it virtually "dies" while other instances will be created.
Now how do i make this Person() instance "die" (assuming many many of these instances will be created and i don't want these instances to hang out like ghosts)?
There are several ways i can reference an object:
john = Person('john')
or
people = []
people.append(Person('john'))
or
people = {}
people['john'] = Person('john')
What is the best way to keep my program clean, freeing resources optimally? And what is the best way then to reference my object so i can control the deletion of the object?
Maybe this also can help:
>>> # Create a simple object with a verbose __del__ to track gc.
>>> class C:
... def __del__(self):
... print "delete object"
...
>>> c = C()
>>> # Delete the object c successfully.
>>> del c
delete object
>>> # Deletion of an object when it go out of the scope where it was defined.
>>> def f():
... c = C()
...
>>> f()
delete object
>>> c = C()
>>> # Create another reference of the object.
>>> b = c
>>> # The object wasn't destructed the call of del only decremented the object reference.
>>> del c
>>> # Now the reference counter of the object reach 0 so the __del__ was called.
>>> del b
delete object
>>> # Create now a list that hold all the objects.
>>> l = [C(), C()]
>>> del l
delete object
delete object
>>> # Create an object that have a cyclic reference.
>>> class C:
... def __init__(self):
... self.x = self
... def __del__(self):
... print "delete object"
...
>>> c = C()
>>> # Run the garbage collector to collect object.
>>> gc.collect()
9
>>> # the gc.garbage contain object that the gc found unreachable and could not be freed.
>>> gc.garbage
[<__main__.C instance at 0x7ff588d84368>]
>>> # Break the cyclic reference.
>>> c.x = None
>>> # And now we can collect this object.
>>> del c
delete object
>>> # Create another object with cyclic reference.
>>> c = C()
>>> # When closing the interactive python interpreter the object will be collected.
delete object
Refrences : del method ; gc module ; weakref module
None of this really has anything to do with garbage collection.
Python's main method of memory management uses reference counting.
In all cases above, Python keeps a count of all the references to the object, and when there are none left, the object is deleted (similar to std::shared_pointer in C++).
References get decreased when
the object holding them is either explicitly deleted (via del)
or goes out of scope (see also here (esp. ex. 8)).
In your case, this applies to either the john object, or either of the people containers. They go out of scope at the end of the function that created them (assuming they are not returned to the calling function). The vast majority of the time, you can just let them go out of scope - it's only when you create really heavy objects or collections - say inside a big loop - that you might want to consider explicitly using del.
Garbage collection really only comes into play when there are reference cycles
- for instance, when an object refers to itself. Like:
a = []
a.append(a)
Again, this happens automatically, and you shouldn't need to do anything special.
I find that most programs create and dispose of objects quite naturally, so I never normally worry about it.
Some examples:
person = Person('john')
person = Person('james')
# Whoops! 'john' has died!
people = []
people.append(Person('john'))
# ...
# All 'Persons' live in people
people = []
# Now all 'Persons' are dead (including the list that referenced them)
class House():
def setOwner(self, person):
self.owner = person
house.setOwner(people[0])
# Now a House refers to a Person
people = []
# Now all 'Persons' are dead, except the one that house.owner refers to.
What I assume you are after is this:
people = {}
people['john'] = Person('john')
def removePerson(personName):
del people[personName]
removePerson('john')
In this case people is the master list and you can control when a Person gets added and removed from the list (its a dictionary).
You may have to think through the concept of a person being created and then dying very thoroughly: Once created how does the person first interact with the simulation. Upon death, how should you untangle the references? (Its ok for a person to refer to other stuff, its things like House in my example that would keep a person alive. You could have other objects hold on to just the name of the person).
Previous answers are correct but here is what is recommended according to python 3.7 Document:
"Python does automatic memory management (reference counting for most objects and garbage collection to eliminate cycles). The memory is freed shortly after the last reference to it has been eliminated."
If you really have to do this because of memory management issues you are experiencing with a particular case then import the gc library and just do this
del self.someInstanceOfyourClass
gc.collect()
here is a simple example https://github.com/nanoseconds/PythonTest/blob/master/test.py