15 C
London
Wednesday, September 4, 2024

11 Python Magic Strategies Each Programmer Ought to Know


11 Python Magic Strategies Each Programmer Ought to Know
Picture by Creator

 

In Python, magic strategies enable you emulate the conduct of built-in capabilities in your Python lessons. These strategies have main and trailing double underscores (__), and therefore are additionally known as dunder strategies.

These magic strategies additionally enable you implement operator overloading in Python. You’ve most likely seen examples of this. Like utilizing the multiplication operator * with two integers offers the product. Whereas utilizing it with a string and an integer okay offers the string repeated okay occasions:

 >>> 3 * 4
12
>>> 'code' * 3
'codecodecode'

 

On this article, we’ll discover magic strategies in Python by making a easy two-dimensional vector Vector2D class.

We’ll begin with strategies you’re doubtless accustomed to and progressively construct as much as extra useful magic strategies.

Let’s begin writing some magic strategies! 

 

 

Think about the next Vector2D class:

 

When you create a category and instantiate an object, you possibly can add attributes like so: obj_name.attribute_name = worth.

Nevertheless, as a substitute of manually including attributes to each occasion that you simply create (not fascinating in any respect, in fact!), you want a strategy to initialize these attributes while you instantiate an object.

To take action you possibly can outline the __init__ methodology. Let’s outline the outline the __init__ methodology for our Vector2D class:

class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

v = Vector2D(3, 5)

 

 

Once you attempt to examine or print out the item you instantiated, you’ll see that you do not get any useful info. 

v = Vector2D(3, 5)
print(v)

 

Output >>> <__main__.Vector2D object at 0x7d2fcfaf0ac0>

 

This is the reason you must add a illustration string, a string illustration of the item. To take action, add a __repr__ methodology like so:

class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Vector2D(x={self.x}, y={self.y})"

v = Vector2D(3, 5)
print(v)

 

Output >>> Vector2D(x=3, y=5)

 

The __repr__ ought to embody all of the attributes and knowledge wanted to create an occasion of the category. The __repr__ methodology is usually used for the aim of debugging.

 

 

The __str__ can be used so as to add a string illustration of the item. Generally, the __str__ methodology is used to supply information to the tip customers of the category.

Let’s add a __str__ methodology to our class:

class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return f"Vector2D(x={self.x}, y={self.y})"

v = Vector2D(3, 5)
print(v)

 

Output >>> Vector2D(x=3, y=5)

 

If there isn’t any implementation of __str__, it falls again to __repr__. So for each class that you simply create, you must—on the minimal—add a __repr__ methodology. 

 

 

Subsequent, let’s add a technique to examine for equality of any two objects of the Vector2D class. Two vector objects are equal if they’ve similar x and y coordinates.

Now create two Vector2D objects with equal values for each x and y and evaluate them for equality:

v1 = Vector2D(3, 5)
v2 = Vector2D(3, 5)
print(v1 == v2)

 

The result’s False. As a result of by default the comparability checks for equality of the item IDs in reminiscence.

 

Let’s add the __eq__ methodology to examine for equality:

class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Vector2D(x={self.x}, y={self.y})"

    def __eq__(self, different):
        return self.x == different.x and self.y == different.y

 

The equality checks ought to now work as anticipated:

v1 = Vector2D(3, 5)
v2 = Vector2D(3, 5)
print(v1 == v2)

 

 

 

Python’s built-in len() perform helps you compute the size of built-in iterables. Let’s say, for a vector, size ought to return the variety of parts that the vector incorporates. 

So let’s add a __len__ methodology for the Vector2D class:

class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Vector2D(x={self.x}, y={self.y})"

    def __len__(self):
        return 2

v = Vector2D(3, 5)
print(len(v))

 

All objects of the Vector2D class are of size 2:

 

 

Now let’s consider frequent operations we’d carry out on vectors. Let’s add magic strategies so as to add and subtract any two vectors.

In case you immediately attempt to add two vector objects, you’ll run into errors. So you must add an __add__ methodology:

class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Vector2D(x={self.x}, y={self.y})"

    def __add__(self, different):
        return Vector2D(self.x + different.x, self.y + different.y)

 

Now you can add any two vectors like so:

v1 = Vector2D(3, 5)
v2 = Vector2D(1, 2)
outcome = v1 + v2
print(outcome)

 

Output >>> Vector2D(x=4, y=7)

 

 

Subsequent, let’s add a __sub__ methodology to calculate the distinction between any two objects of the Vector2D class:

class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Vector2D(x={self.x}, y={self.y})"

    def __sub__(self, different):
        return Vector2D(self.x - different.x, self.y - different.y)

 

v1 = Vector2D(3, 5)
v2 = Vector2D(1, 2)
outcome = v1 - v2
print(outcome)

 

Output >>> Vector2D(x=2, y=3)

 

 

We are able to additionally outline a __mul__ methodology to outline multiplication between objects.

Let’s implement let’s deal with 

  • Scalar multiplication: the multiplication of a vector by scalar and 
  • Internal product: the dot product of two vectors 
class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Vector2D(x={self.x}, y={self.y})"

    def __mul__(self, different):
        # Scalar multiplication
        if isinstance(different, (int, float)):
            return Vector2D(self.x * different, self.y * different)
        # Dot product
        elif isinstance(different, Vector2D):
            return self.x * different.x + self.y * different.y
        else:
            elevate TypeError("Unsupported operand kind for *")

 

Now we’ll take a few examples to see the __mul__ methodology in motion.

v1 = Vector2D(3, 5)
v2 = Vector2D(1, 2)

# Scalar multiplication
result1 = v1 * 2
print(result1)  
# Dot product
result2 = v1 * v2
print(result2)

 

Output >>>

Vector2D(x=6, y=10)
13

 

 

The __getitem__ magic methodology permits you to index into the objects and entry attributes or slice of attributes utilizing the acquainted square-bracket [ ] syntax.

For an object v of the Vector2D class:

  • v[0]: x coordinate
  • v[1]: y coordinate

In case you attempt accessing by index, you’ll run into errors:

v = Vector2D(3, 5)
print(v[0],v[1])

 

---------------------------------------------------------------------------

TypeError                             	Traceback (most up-to-date name final)

 in ()
----> 1 print(v[0],v[1])

TypeError: 'Vector2D' object will not be subscriptable

 

Let’s implement the __getitem__ methodology: 

class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Vector2D(x={self.x}, y={self.y})"

    def __getitem__(self, key):
        if key == 0:
            return self.x
        elif key == 1:
            return self.y
        else:
            elevate IndexError("Index out of vary")

 

Now you can entry the weather utilizing their indexes as proven:

v = Vector2D(3, 5)
print(v[0])  
print(v[1])

 

 

 

With an implementation of the __call__ methodology, you possibly can name objects as in the event that they have been capabilities. 

Within the Vector2D class, we will implement a __call__ to scale a vector by a given issue:

class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y
 	 
    def __repr__(self):
        return f"Vector2D(x={self.x}, y={self.y})"

    def __call__(self, scalar):
        return Vector2D(self.x * scalar, self.y * scalar)

 

So if you happen to now name 3, you’ll get the vector scaled by issue of three:

v = Vector2D(3, 5)
outcome = v(3)
print(outcome)

 

Output >>> Vector2D(x=9, y=15)

 

 

The __getattr__ methodology is used to get the values of particular attributes of the objects.

For this instance, we will add a __getattr__ dunder methodology that will get known as to compute the magnitude (L2-norm) of the vector:

class Vector2D:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Vector2D(x={self.x}, y={self.y})"

    def __getattr__(self, title):
        if title == "magnitude":
            return (self.x ** 2 + self.y ** 2) ** 0.5
        else:
            elevate AttributeError(f"'Vector2D' object has no attribute '{title}'")

 

Let’s confirm if this works as anticipated:

v = Vector2D(3, 4)
print(v.magnitude)

 

 

 

That is all for this tutorial! I hope you realized the best way to add magic strategies to your class to emulate the conduct of built-in capabilities.

We’ve lined among the most helpful magic strategies. However this isn’t this isn’t an exhaustive checklist. To additional your understanding, create a Python class of your alternative and add magic strategies relying on the performance required. Hold coding!
 
 

Bala Priya C is a developer and technical author from India. She likes working on the intersection of math, programming, knowledge science, and content material creation. Her areas of curiosity and experience embody DevOps, knowledge science, and pure language processing. She enjoys studying, writing, coding, and low! Presently, she’s engaged on studying and sharing her information with the developer neighborhood by authoring tutorials, how-to guides, opinion items, and extra.



Latest news
Related news

LEAVE A REPLY

Please enter your comment!
Please enter your name here