Dunder / magic functions in Python

Senior Data Engineer • Contractor / Freelancer • GCP & AWS Certified
Search for a command to run...

Senior Data Engineer • Contractor / Freelancer • GCP & AWS Certified
No comments yet. Be the first to comment.
Concise guides to Python features and patterns most useful for data engineering — from built-ins to standard library modules.
Ever encountered the with statement? I've seen them around lots of times, but once, when asked about Context Managers during an interview, I didn't know what they were! Here's what to know about them, so you won't repeat my mistake. You might've used...
Here's a useful Dataform concept: pre_operations and post_operations. As the name implies, these represent a set of actions that run before and after the main operation (table, view, or SQL operations

BigQuery has always been a SQL engine for tabular data. Object tables add an interesting twist to that. Instead of rows containing values, an object table gives you one row per file — pointing at da

Query your data lake with warehouse-grade security and performance — without moving a single file.

Ever run a heavy BigQuery SQL query, processed gigabytes of data — and then accidentally closed the tab or forgot to save the results? 😬 Don't re-run it. Your results are still there. BigQuery automa

You can use query parameters in BigQuery hashtag#SQL (now in the console as well!) — but how are they different from variables, and when should you use each? Both parameters and variables act as place

One thing you might encounter in Python are the "dunder" (because of the double underscore before and after their name) or "magic" methods, because they're special. You should have surely seen the '__init__' method in Python code.
Now, 'dunder' methods are special methods that allow classes to interact with the built-in functions or operators.
We need them because a Python built-in, e.g. the 'greater than' sign (>), does not know how to perform a comparison between two instances of a class we define.
The same would go for many other behaviors such as looping through the object, representing it as a string or finding out its length. There are dozens of dunder/magic methods, but I'll illustrate a few below in a short example.
Let's build a Skyscraper class and implement some magic functions that will allow for comparison, ordering and representation of such classes.
class Skyscraper:
def __init__(self, name, height):
self.name = name
self.height = height
def __repr__(self):
return f"Skyscraper({self.name},{self.height})"
def __str__(self):
return f"{self.name} @ {self.height} "
def __eq__(self, other):
if not isinstance(other, Skyscraper):
return NotImplemented
return self.height == other.height
def __ge__(self, other):
if not isinstance(other, Skyscraper):
return NotImplemented
return self.height >= other.height
def __lt__(self, other):
if not isinstance(other, Skyscraper):
return NotImplemented
return self.height < other.height
Now, let's see them in action:
# Creating 3 Skyscraper objects
burj_khalifa = Skyscraper('Burj Khalifa', 818) # Height = 818
taipei_101 = Skyscraper('Taipei 101', 508) # Height = 508
one_wtc = Skyscraper('One WTC', 541) # Height = 541
# String representation
print(str(burj_khalifa)) #Output Burj Khalifa @ 818
# Checking equality
print(burj_khalifa == taipei_101) # Output: False (because heights are not equal)
# Checking greater than or equal
print(burj_khalifa >= taipei_101) # Output: True (818 >= 508)
print(taipei_101 >= one_wtc) # Output: False
# Checking less than
print(one_wtc < taipei_101) # Output: False
print(one_wtc < burj_khalifa) # Output: True
# Sorting an array of skyscrapers ascendingly
print(sorted([burj_khalifa, taipei_101, one_wtc]))
# Output [Skyscraper(Taipei 101,508), Skyscraper(One WTC,541), Skyscraper(Burj Khalifa,818)]
Thanks for reading!
Found it useful? Subscribe to my Analytics newsletter at notjustsql.com.