In Python Everything is an Object
Python is an object-oriented programming language and in Python, everything is an object. This means that types---int, float, bool, string, etc---are actually classes and variables are instances of these classes. The fact that these types are classes means that instances of a type have some associated attributes and methods which are built into the class. For example, lists have the append method accessed using list_name.append().
The implications of everything being an object in Python are far reaching and I will discuss some of these implications below.
Every Python object has a type, an ID, and a value. Once an object is created, its ID does not change even if the object is altered. The ID is stored in memory and can be used to reference the object. An object's ID can be accessed using the function id():
id(object_name)
Similarly, an object's type can be accessed using the type() function:
type(object_name)
Mutable objects which Python users can change the state and value of. Dictionaries, sets, lists, custom objects, and byte arrays are all mutable. It is possible to add, remove, and change the value of elements inside these objects. Changes to a mutable object do not affect the object's identity. When a variable assigned to a mutable object, both the variable and the object refer to the same place in memory and the object can be referenced and changed directly.
Recommended by LinkedIn
In contrast, immutable objects cannot be modified after they are created. Examples of immutable objects include function arguments, integers, floats, strings, tuples, frozensets, dictionary keys, and bytes. Immutable objects are useful in situations in which we do not want values to change. For example, we want dictionary keys to be unique because that is what makes dictionaries useful. It would be difficult to do math if we accidently changed the values of numbers:
1 = 2
return 1 + 1
4
uh oh...
When immutable objects are assigned to a variable, the variable points to a different place in memory. Immutable objects cannot be changed by reference because any change creates a new object.
As discussed, mutable objects can be altered without changing the object's ID. Immutable objects can be changed but when they are a new object is created with a new object ID. Mutable and immutable objects are handled differently in memory. Mutable objects take up more room in memory because Python may need to reallocate memory for mutable objects when the user changes them. Immutable objects are stored more efficiently in memory because Python can reuse memory for identical objects. For example, NSMALLPOSINTS---positive integer between 0 and 256---are pooled so that different variables point to the same place in memory. Similarly, NSMALLNEGINTS range from -1 to -5. These numbers are preallocated when Python is launched to help save space in memory because these numbers are frequently used.
Another important way that mutable and immutable objects differ is in how the are handled when passed as arguments to functions. Immutable objects passed to a function are effectively a copy of the object. Changes made to the object within the function do not affect the original object. Mutable objects passed to a function are effectively references to memory address of that object. So changes made to that object within the function do affect the original object. Similarly, aliases for mutable objects point to the same place in memory as the original reference and therefore a change made to either changes the other. Aliases for immutable objects point to the same object as the original reference but any changes to the alias would result in the creation of a new object.