Programming in Python: objects everywhere!

Programming in Python: objects everywhere!

Python is a high-level programming language widely used around the world to develop applications of all kinds. It was developed in the 90s by the informatic scientist Guido Van Rossum, that he wanted to create a programming language easy to learn, write and understand. A very important feature of Python is that it is an interpreted language. This means that we can run successfully our programs directly, without a previous compiling process that translates the code to machine language: it is interpreted and executed. Also, the simple syntax of Python, similar to human language, and it open-code multiplatform allows develops a multiple types of projects with few drawbacks, for example: artificial intelligence, machine learning, big data and data sciences.

Python is one of the languages leaders in the object-oriented programming (OOP) paradigm. This model of programming is used to structure the problem into small and simple pieces of code format, where the errors are minimized, and the code can be reuse and easy to keep. The OOP is governed by 4 principles: encapsulation, abstraction, inheritance and polymorphisms. Python avoids exposure code unnecessary through encapsulation and abstraction, for example, so that programming in it is a secure and efficient option. The fundamental brick in OOP are objects: abstractions for data ✨

Objects: identity and type

Two objects important features are identity and type.

The identity of an object is the object's address in memory. It is an unchanged value once the object has been created. We can obtain the identity of an object using the id() function: returns a unique and constant integer during its exists.

# Function syntax:
id(object)


# Examples:
a = 1
b = "hello!"
c = [red, blue, yellow]

print(id(a)) # Output: 1620096949
print(id(b)) # Output: 53021544
print(id(c)) # Output: 450751920

        

Objects with non-overlapping lifetimes may have the same id() value. You can compare the objects identity using the is operator. If two objects are the same object, that means both referring to the same object, then a is b and id(a) == id(b) are True.

a = 2
b = 2

print(a is b) # Output: True
print(id(a) == id(b)) # Output: True

print(id(a)) # Output: 1141324761
print(id(b)) # Output: 1141324761
        

As another feature, we know that an object can be of one type or another. The type of an object determinate, for example, different built-in functions available. Also, this feature is unchanged once the object has been created. For find the object type, we should use the type() or isinstance() functions. isinstance return is True, is object type is equal to classinfo, otherwise an exception is raised.

# Function syntax:
type(object)
isinstance(object, classinfo)

# Examples:
a = "I'm a string B)"
print (type(a)) # Output: <class 'str'>
print (isinstance(a, str)) # Output: True

b = 15
print (type(b)) # Output: <class 'int'>
print (isinstance(b, int)) # Output: True

c = 3.14
print (type(c)) # Output: <class 'float'>
print (isinstance(c, str)) # Output: NameError: name 'str' is not defined

d = [2, 4, 6, 8]
print (type(d)) # Output: <class 'list'>
print (isinstance(d, tuple)) # Output: NameError: name 'tuple' is not defined
        

Mutable and immutable objects

Type and identity of an object are unchanged values. However, the value of some objects can be changed. If an object can change his value after its creation, is a mutable object. On the other hand, if an object has an value once it is created and it can't change, it is a immutable object. This concept is known as mutability, and is depending on the object type. For example, lists, dictionaries, sets and bytearrays are mutable objects, and integers, floats, complex numbers, tuples, strings, bytes or frozen sets are immutable objects.

# Mutable object example:
stock = ["mouse", "keyboard", "airpods"]
stock[1] = "speaker"
print(stock) # Output: ["mouse", "speaker", "airpods"]

# Immutable object example:
a = 3
a = 6
# After a = 6, a is referring to a new memory direction, that contains the 6 value. However, the 3 value is keeping in the memory anyway.
        

An curious example is a tuple of lists. Tuples are immutable objects, thus, we can't change its values, but lists inside the tuple are mutable objects. So, in this case, we can change the lists values but not the tuple values:

my_tuple = ([2, 4], [1, 3])
my_tuple[1][1] = 0
my_tuple[0][1] = 0
print(my_tuple) # Output: ([2, 0], [1, 0])

# The mutables objects here are lists, but could be any type of mutable objects
        

Another case are frozen sets. These objects are immutable versions of sets objects. In a set, is allowed to change its values, but in a frozen set we can't modify any value: remains the same values after its creation.

Integer pre-allocation when CPython starts

To optimize and economize memory usage, CPython takes this strategy: at the moment of starts, pre-allocates the first 262 integers (the range of numbers -5; 256 inclusive). These are allocated in an array that occupy specifics spaces of memory. At the moment when we "create" a integer variable in that range, really we are created a variable that points to the space of memory that save this integer value.

For this reason, the macros NSMALLPOSINTS and NSMALLNEGINTS were created. Respectively, these refer to -5 and 256. The integers array is set to this particular range because these are the most commonly used numbers.

Importance to be a mutable or immutable object

Python treat differently the objects, in function to its mutability nature. Immutable objects are quicker to access vs. mutable objects, but in opposition, these last requires less processing because don't need to generate copies of any type, so are easy to change.

Function arguments: how are passed?

The type of objects that we used in our functions affects considerably the memory efficiency. Thus, it is recommended to use the correct objects to optimize the programs you created.

In case of mutable objects, a function could edit its value because the reference points to the same memory space. Of this way, the original objects can be changed.

>>> def duplicate(list):
...   list *= 2
...
>>> my_list = [0, 2, 4]
>>> duplicate(my_list)
>>> my_list
>>> [0, 2, 4, 0, 2, 4]            

Immutable objects adopt a different behavior. These objects can be called by reference into a function, precisely because its values will remain unchanged.

>>> def square(n)
...   n *= n
...
>>> my_int = 4
>>> square(my_int)
>>> my_int
>>> 4        

To view or add a comment, sign in

More articles by Belén Matto Cardell

  • Regularization techniques in Machine Learning

    Today we find in machine learning the solution to solve a lot of questions. Creating specific models, we can apply this…

    1 Comment

Insights from the community

Others also viewed

Explore topics