Python Frequently Asked Questions, Release 3.9.5 Chapter 3. Design and History FAQ 42 Tuples are immutable, meaning that once a tuple has been created, you can’t replace any of its elements with a new value. Lists are mutable, meaning that you can always change a list’s elements. Only immutable elements can be used as dictionary keys, and hence only tuples and not lists can be used as keys. Lists, on the other hand, are more like arrays in other languages. They tend to hold a varying number of objects all of which have the same type and which are operated on one-by-one. For example,$_{os.listdir('.')}$ returns a list of strings representing the files in the current directory. Functions which operate on this output would generally not break if you added another file or two to the directory. Lists and tuples, while similar in many respects, are generally used in fundamentally different ways. Tuples can be thought of as being similar to Pascal records or C structs; they’re small collections of related data which may be of different types which are operated on as a group. For example, a Cartesian coordinate is appropriately represented as a tuple of two or three numbers. If you want to force Python to delete certain things on deallocation use the$_{atexit}$module to run a function that will force those deletions. Objects referenced from the global namespaces of Python modules are not always deallocated when Python exits. This may happen if there are circular references. There are also certain bits of memory that are allocated by the C library that are impossible to free (e.g. a tool like Purify will complain about these). Python is, however, aggressive about cleaning up memory on exit and does try to destroy every single object. Traditional GC also becomes a problem when Python is embedded into other applications. While in a standalone Python it’s fine to replace the standard malloc() and free() with versions provided by the GC library, an application embedding Python may want to have its own substitute for malloc() and free(), and may not want Python’s. Right now, CPython works with anything that implements malloc() and free() properly. For one thing, this is not a C standard feature and hence it’s not portable. (Yes, we know about the Boehm GC library. It has bits of assembler code for most common platforms, not for all of them, and although it is mostly transparent, it isn’t completely transparent; patches are required to get Python to work with it.) If you want to write code that will work with any Python implementation, you should explicitly close the file or use the$_{with}$ statement; this will work regardless of memory management scheme: Indeed, using CPython’s reference counting and destructor scheme, each new assignment to f closes the previous file. With a traditional GC, however, those file objects will only get collected (and closed) at varying and possibly long intervals. for file in very_long_list_of_files: f =open(file) c =f.read(1) for file in very_long_list_of_files: with open(file) as f: c =f.read(1) 3.17 Why are there separate tuple and list data types? 3.16 Why isn’t all memory freed when CPython exits? 3.15 Why doesn’t CPython use a more traditional garbage collec- tion scheme?