Python: objects and "first-class everything"
Svitlana Pavlovska
?? Full-Stack Web Developer | JavaScript | Node.js | React
Programming languages can be categorized based on their features, giving rise to various paradigms such as procedural, object-oriented, or functional programming. Python falls under the object-oriented paradigm, where the understanding of objects and their characteristics holds paramount importance.?In this article, we will define objects, explain what type and id functions do, contrast mutable and immutable objects and shed light on how differently Python treats them.
Object in Python
In Python, an object is more than just data; it embodies associated metadata in the form of attributes and properties, as well as actions in the form of functions and methods. The concept of "first-class" in Python signifies that every element in the language is treated as a first-class citizen, granting them equal standing in how they can be employed and manipulated within the language.
Every piece of data, or object, residing in memory is identified by a unique numeric value, often referred to as the object's identity. This identity serves as a distinguishing feature between different objects. You can obtain an object's identity using the id() function, which assigns a constant identity to an object during its lifespan when passed as a parameter.
Conversely, the type() function provides information about an object's class or data type, revealing the nature of the object. Let's delve into the example:
>>> 7
7
>>> id(7)
9789152
>>> type(7)
<class 'int'>
The number 7 is an object which has a unique id (9789152) and belongs to the class of the type ?int?.?
?Int? is one of the built-in classes in Python, and every time you are using an integer, it will be an object belonging to this class, and the object itself will be an instance of that class.
Mutable and Immutable Objects
In Python, objects fall into two primary categories: mutable and immutable. Distinguishing between these categories is pivotal as it significantly influences how you manipulate data in Python.
Mutable objects, as the name implies, permit alterations to their state or value after creation. Common examples of mutable objects include lists, dictionaries, sets and byte arrays. Modifying the contents of a mutable object doesn't necessitate creating a new object. When you assign a mutable object to a variable or pass it to a function, you're essentially dealing with a reference to the original object. Any modifications to the object propagate to all references to that object.
>>> list = [1, 2, 3]
>>> id(list)
140660790020480
>>> list.append(4)
>>> print(list)
[1, 2, 3, 4]
>>> id(list)
140660790020480
In contrast, immutable objects are unalterable after their creation. This category encompasses numbers(integers, floats or complex), strings, tuples, frozen sets and bytes. When you attempt to modify an immutable object, Python generates a new object with the updated value instead of altering the original. Immutable objects are stored by value, leading to object copying when assigned to variables or passed as function arguments. Modifications to immutable objects result in the creation of new objects, leaving the original object unchanged.
>>> string = "Hello"
>>> string[5] = "!"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> string = "Hello"
>>> print(string)
Hello
>>> id(string)
140660790021808
>>> string = "Hi"
>>> print(string)
Hi
>>> id(string)
140660790022000
While tuples and frozen sets are considered immutable objects in Python, they possess the capability to contain references to mutable objects. Thus, while you cannot modify the tuple or frozen set itself, you can modify the contents of the mutable objects they reference.
领英推荐
>>> tuple_mut = ([1, 2, 3], "hello")
>>> tuple_mut[0][1] = 5
>>> print(tuple_mut)
([1, 5, 3], 'hello')
Object reference or assignment
In Python, when you pass an object to a function, you are passing a reference to the object itself, not a copy of the object. This is known as call-by-object-reference or call-by-assignment.
If you pass an immutable object (e.g., a number, string, or tuple) to a function and change the value of the object inside the function, the original object outside of the function will not be affected. This is because immutable objects cannot be changed.
>>> string = "Sarah"
>>> def change(string):
string = "John"
print("Inside the function is:", string)
>>> change(string)
Inside the function is : John
>>> print("Outside the function is", string)
Outside the function is Sarah
If you pass a mutable object (e.g., a list or dictionary) to a function and change the state of the object inside the function, the original object outside of the function will also be affected. This is because mutable objects can be changed.
>>> def add_num(list):
list.append(5)
print("Inside the function:", list)
>>> my_list = [1, 2, 3, 4]
>>> add_num(my_list)
Inside the function: [1, 2, 3, 4, 5]
print("Outside the function:", my_list)
Outside the function: [1, 2, 3, 4, 5]
Aliasing mechanism
In Python, variable is just a name given to an object in the memory. When we assign the value of one variable to another, these two variables reference the same object and share the same memory address, indicating that they are pointing to the identical object. This forms the basis of the aliasing mechanism, where multiple variables reference the same object. Any modifications to the object through one alias will be reflected in all aliases since they all point to the same memory location.
>>> b = [1, 3, 4]
>>> c = [1, 3, 4]
>>> id(b)
140660790020864
>>> id(c)
140660790021248
>>> b = c
>>> id(b)
140660790021248
>>> id(c)
140660790021248
NSMALLPOSINTS and NSMALLNEGINTS macros
Python employs constants known as NSMALLPOSINTS and NSMALLNEGINTS to represent pre-allocated positive and negative integers (from -5 to 256). These constants optimize memory utilization for frequently used small integers. Instead of creating new objects for these commonly used integers, Python employs these pre-allocated integers to conserve memory. The specific values of NSMALLPOSINTS and NSMALLNEGINTS are chosen to accommodate the most frequently occurring integers in Python programs, thus enhancing memory efficiency for these values.
>>> x = 9
>>> y = 9
>>> id(x)
9789216
>>> id(y)
9789216
>>> a = 900
>>> b = 900
>>> id(a)
140660790443024
>>> id(b)
140660790443152
In conclusion, the comprehension of the object-oriented principles and incorporation of the insights above are indispensable for mastering the language and should empower to write efficient and robust code.