• About
  • Advertise
  • Privacy & Policy
  • Contact
Thursday, December 25, 2025
  • Login
  • Home
    • Home – Layout 1
    • Home – Layout 2
    • Home – Layout 3
    • Home – Layout 4
    • Home – Layout 5
    • Home – Layout 6
  • News
    • All
    • Business
    • Politics
    • Science
    • World
    Hillary Clinton in white pantsuit for Trump inauguration

    Hillary Clinton in white pantsuit for Trump inauguration

    Amazon has 143 billion reasons to keep adding more perks to Prime

    Amazon has 143 billion reasons to keep adding more perks to Prime

    Shooting More than 40 Years of New York’s Halloween Parade

    Shooting More than 40 Years of New York’s Halloween Parade

    These Are the 5 Big Tech Stories to Watch in 2017

    These Are the 5 Big Tech Stories to Watch in 2017

    Why Millennials Need to Save Twice as Much as Boomers Did

    Why Millennials Need to Save Twice as Much as Boomers Did

    Doctors take inspiration from online dating to build organ transplant AI

    Doctors take inspiration from online dating to build organ transplant AI

    Trending Tags

    • Trump Inauguration
    • United Stated
    • White House
    • Market Stories
    • Election Results
  • Tech
    • All
    • Apps
    • Gadget
    • Mobile
    • Startup
    The Legend of Zelda: Breath of the Wild gameplay on the Nintendo Switch

    The Legend of Zelda: Breath of the Wild gameplay on the Nintendo Switch

    Shadow Tactics: Blades of the Shogun Review

    Shadow Tactics: Blades of the Shogun Review

    macOS Sierra review: Mac users get a modest update this year

    macOS Sierra review: Mac users get a modest update this year

    Hands on: Samsung Galaxy A5 2017 review

    Hands on: Samsung Galaxy A5 2017 review

    The Last Guardian Playstation 4 Game review

    The Last Guardian Playstation 4 Game review

    These Are the 5 Big Tech Stories to Watch in 2017

    These Are the 5 Big Tech Stories to Watch in 2017

    Trending Tags

    • Nintendo Switch
    • CES 2017
    • Playstation 4 Pro
    • Mark Zuckerberg
  • Entertainment
    • All
    • Gaming
    • Movie
    • Music
    • Sports
    The Legend of Zelda: Breath of the Wild gameplay on the Nintendo Switch

    The Legend of Zelda: Breath of the Wild gameplay on the Nintendo Switch

    macOS Sierra review: Mac users get a modest update this year

    macOS Sierra review: Mac users get a modest update this year

    Hands on: Samsung Galaxy A5 2017 review

    Hands on: Samsung Galaxy A5 2017 review

    Heroes of the Storm Global Championship 2017 starts tomorrow, here’s what you need to know

    Heroes of the Storm Global Championship 2017 starts tomorrow, here’s what you need to know

    Harnessing the power of VR with Power Rangers and Snapdragon 835

    Harnessing the power of VR with Power Rangers and Snapdragon 835

    So you want to be a startup investor? Here are things you should know

    So you want to be a startup investor? Here are things you should know

  • Lifestyle
    • All
    • Fashion
    • Food
    • Health
    • Travel
    Shooting More than 40 Years of New York’s Halloween Parade

    Shooting More than 40 Years of New York’s Halloween Parade

    Heroes of the Storm Global Championship 2017 starts tomorrow, here’s what you need to know

    Heroes of the Storm Global Championship 2017 starts tomorrow, here’s what you need to know

    Why Millennials Need to Save Twice as Much as Boomers Did

    Why Millennials Need to Save Twice as Much as Boomers Did

    Doctors take inspiration from online dating to build organ transplant AI

    Doctors take inspiration from online dating to build organ transplant AI

    How couples can solve lighting disagreements for good

    How couples can solve lighting disagreements for good

    Ducati launch: Lorenzo and Dovizioso’s Desmosedici

    Ducati launch: Lorenzo and Dovizioso’s Desmosedici

    Trending Tags

    • Golden Globes
    • Game of Thrones
    • MotoGP 2017
    • eSports
    • Fashion Week
  • Review
    The Legend of Zelda: Breath of the Wild gameplay on the Nintendo Switch

    The Legend of Zelda: Breath of the Wild gameplay on the Nintendo Switch

    Shadow Tactics: Blades of the Shogun Review

    Shadow Tactics: Blades of the Shogun Review

    macOS Sierra review: Mac users get a modest update this year

    macOS Sierra review: Mac users get a modest update this year

    Hands on: Samsung Galaxy A5 2017 review

    Hands on: Samsung Galaxy A5 2017 review

    The Last Guardian Playstation 4 Game review

    The Last Guardian Playstation 4 Game review

    Intel Core i7-7700K ‘Kaby Lake’ review

    Intel Core i7-7700K ‘Kaby Lake’ review

No Result
View All Result
Ai News
Advertisement
  • Home
    • Home – Layout 1
    • Home – Layout 2
    • Home – Layout 3
    • Home – Layout 4
    • Home – Layout 5
    • Home – Layout 6
  • News
    • All
    • Business
    • Politics
    • Science
    • World
    Hillary Clinton in white pantsuit for Trump inauguration

    Hillary Clinton in white pantsuit for Trump inauguration

    Amazon has 143 billion reasons to keep adding more perks to Prime

    Amazon has 143 billion reasons to keep adding more perks to Prime

    Shooting More than 40 Years of New York’s Halloween Parade

    Shooting More than 40 Years of New York’s Halloween Parade

    These Are the 5 Big Tech Stories to Watch in 2017

    These Are the 5 Big Tech Stories to Watch in 2017

    Why Millennials Need to Save Twice as Much as Boomers Did

    Why Millennials Need to Save Twice as Much as Boomers Did

    Doctors take inspiration from online dating to build organ transplant AI

    Doctors take inspiration from online dating to build organ transplant AI

    Trending Tags

    • Trump Inauguration
    • United Stated
    • White House
    • Market Stories
    • Election Results
  • Tech
    • All
    • Apps
    • Gadget
    • Mobile
    • Startup
    The Legend of Zelda: Breath of the Wild gameplay on the Nintendo Switch

    The Legend of Zelda: Breath of the Wild gameplay on the Nintendo Switch

    Shadow Tactics: Blades of the Shogun Review

    Shadow Tactics: Blades of the Shogun Review

    macOS Sierra review: Mac users get a modest update this year

    macOS Sierra review: Mac users get a modest update this year

    Hands on: Samsung Galaxy A5 2017 review

    Hands on: Samsung Galaxy A5 2017 review

    The Last Guardian Playstation 4 Game review

    The Last Guardian Playstation 4 Game review

    These Are the 5 Big Tech Stories to Watch in 2017

    These Are the 5 Big Tech Stories to Watch in 2017

    Trending Tags

    • Nintendo Switch
    • CES 2017
    • Playstation 4 Pro
    • Mark Zuckerberg
  • Entertainment
    • All
    • Gaming
    • Movie
    • Music
    • Sports
    The Legend of Zelda: Breath of the Wild gameplay on the Nintendo Switch

    The Legend of Zelda: Breath of the Wild gameplay on the Nintendo Switch

    macOS Sierra review: Mac users get a modest update this year

    macOS Sierra review: Mac users get a modest update this year

    Hands on: Samsung Galaxy A5 2017 review

    Hands on: Samsung Galaxy A5 2017 review

    Heroes of the Storm Global Championship 2017 starts tomorrow, here’s what you need to know

    Heroes of the Storm Global Championship 2017 starts tomorrow, here’s what you need to know

    Harnessing the power of VR with Power Rangers and Snapdragon 835

    Harnessing the power of VR with Power Rangers and Snapdragon 835

    So you want to be a startup investor? Here are things you should know

    So you want to be a startup investor? Here are things you should know

  • Lifestyle
    • All
    • Fashion
    • Food
    • Health
    • Travel
    Shooting More than 40 Years of New York’s Halloween Parade

    Shooting More than 40 Years of New York’s Halloween Parade

    Heroes of the Storm Global Championship 2017 starts tomorrow, here’s what you need to know

    Heroes of the Storm Global Championship 2017 starts tomorrow, here’s what you need to know

    Why Millennials Need to Save Twice as Much as Boomers Did

    Why Millennials Need to Save Twice as Much as Boomers Did

    Doctors take inspiration from online dating to build organ transplant AI

    Doctors take inspiration from online dating to build organ transplant AI

    How couples can solve lighting disagreements for good

    How couples can solve lighting disagreements for good

    Ducati launch: Lorenzo and Dovizioso’s Desmosedici

    Ducati launch: Lorenzo and Dovizioso’s Desmosedici

    Trending Tags

    • Golden Globes
    • Game of Thrones
    • MotoGP 2017
    • eSports
    • Fashion Week
  • Review
    The Legend of Zelda: Breath of the Wild gameplay on the Nintendo Switch

    The Legend of Zelda: Breath of the Wild gameplay on the Nintendo Switch

    Shadow Tactics: Blades of the Shogun Review

    Shadow Tactics: Blades of the Shogun Review

    macOS Sierra review: Mac users get a modest update this year

    macOS Sierra review: Mac users get a modest update this year

    Hands on: Samsung Galaxy A5 2017 review

    Hands on: Samsung Galaxy A5 2017 review

    The Last Guardian Playstation 4 Game review

    The Last Guardian Playstation 4 Game review

    Intel Core i7-7700K ‘Kaby Lake’ review

    Intel Core i7-7700K ‘Kaby Lake’ review

No Result
View All Result
Ai News
No Result
View All Result
Home Machine Learning

Dunder Methods: The Hidden Gems of Python | by Federico Zabeo | Nov, 2024

AiNEWS2025 by AiNEWS2025
2024-12-11
in Machine Learning
0
Dunder Methods: The Hidden Gems of Python | by Federico Zabeo | Nov, 2024
0
SHARES
0
VIEWS
Share on FacebookShare on Twitter


Actual-world examples on how actively utilizing particular strategies can simplify coding and enhance readability.

Federico Zabeo

Towards Data Science

Dunder strategies, although presumably a primary subject in Python, are one thing I’ve usually observed being understood solely superficially, even by individuals who have been coding for fairly a while.

Disclaimer: This can be a forgivable hole, as most often, actively utilizing dunder strategies “merely” accelerates and standardize duties that may be executed in another way. Even when their use is important, programmers are sometimes unaware that they’re writing particular strategies that belong to the broader class of dunder strategies.

Anyway, if you happen to code in Python and usually are not aware of this subject, or if you happen to occur to be a code geek intrigued by the extra native facets of a programming language like I’m, this text may simply be what you’re searching for.

Appearances can deceive… even in Python!

If there’s one factor I discovered in my life is that not every thing is what it looks like at a primary look, and Python is not any exception.

Photograph by Robert Katzki on Unsplash

Allow us to take into account a seemingly easy instance:

class EmptyClass:
move

That is the “emptiest” customized class we are able to outline in Python, as we didn’t outline attributes or strategies. It’s so empty you’ll suppose you are able to do nothing with it.

Nonetheless, this isn’t the case. For instance, Python is not going to complain if you happen to attempt to create an occasion of this class and even examine two cases for equality:

empty_instance = EmptyClass()
another_empty_instance = EmptyClass()

>>> empty_instance == another_empty_instance
False

In fact, this isn’t magic. Merely, leveraging a normal object interface, any object in Python inherits some default attributes and strategies that enable the person to all the time have a minimal set of doable interactions with it.

Whereas these strategies could appear hidden, they aren’t invisible. To entry the out there strategies, together with those assigned by Python itself, simply use the dir() built-in operate. For our empty class, we get:

>>> dir(EmptyClass)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
'__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__', '__weakref__']

It’s these strategies that may clarify the behaviour we noticed earlier. For instance, because the class truly has an __init__ methodology we shouldn’t be shocked that we are able to instantiate an object of the category.

Meet the Dunder Strategies

All of the strategies proven within the final output belongs to the particular group of — guess what — dunder strategies. The time period “dunder” is brief for double underscore, referring to the double underscores in the beginning and finish of those methodology names.

They’re particular for a number of causes:

  1. They’re constructed into each object: each Python object is provided with a particular set of dunder strategies decided by its sort.
  2. They’re invoked implicitly: many dunder strategies are triggered mechanically by interactions with Python’s native operators or built-in features. For instance, evaluating two objects with == is equal to calling their __eq__ methodology.
  3. They’re customizable: you may override present dunder strategies or outline new ones in your lessons to present them customized conduct whereas preserving their implicit invocation.

For many Python builders, the primary dunder they encounter is __init__, the constructor methodology. This methodology is mechanically referred to as whenever you create an occasion of a category, utilizing the acquainted syntax MyClass(*args, **kwargs) as a shortcut for explicitly calling MyClass.__init__(*args, **kwargs).

Regardless of being essentially the most generally used, __init__ can also be some of the specialised dunder strategies. It doesn’t absolutely showcase the pliability and energy of dunder strategies, which may assist you to redefine how your objects work together with native Python options.

Make an object fairly

Allow us to outline a category representing an merchandise on the market in a store and create an occasion of it by specifying the identify and value.

class Merchandise:
def __init__(self, identify: str, value: float) -> None:
self.identify = identify
self.value = value

merchandise = Merchandise(identify="Milk (1L)", value=0.99)

What occurs if we attempt to show the content material of the merchandise variable? Proper now, one of the best Python can do is inform us what sort of object it’s and the place it’s allotted in reminiscence:

>>> merchandise
<__main__.Merchandise at 0x00000226C614E870>

Let’s attempt to get a extra informative and fairly output!

Photograph by Shamblen Studios on Unsplash

To do this, we are able to override the __repr__ dunder, which output will probably be precisely what will get printed when typing a category occasion within the interactive Python console but in addition — as quickly as the opposite dunder methodology __str__ isn’t override — when trying a print() name.

Notice: it’s a widespread observe to have __repr__ present the mandatory syntax to recreate the printed occasion. So in that latter case we count on the output to be Merchandise(identify=”Milk (1L)”, value=0.99).

class Merchandise:
def __init__(self, identify: str, value: float) -> None:
self.identify = identify
self.value = value

def __repr__(self) -> str:
return f"{self.__class__.__name__}('{self.identify}', {self.value})"

merchandise = Merchandise(identify="Milk (1L)", value=0.99)

>>> merchandise # On this instance it's equal additionally to the command: print(merchandise)
Merchandise('Milk (1L)', 0.99)

Nothing particular, proper? And you’ll be proper: we may have carried out the identical methodology and named it my_custom_repr with out getting indo dunder strategies. Nonetheless, whereas anybody instantly understands what we imply with print(merchandise) or simply merchandise, can we are saying the identical for one thing like merchandise.my_custom_repr()?

Outline interplay between an object and Python’s native operators

Think about we wish to create a brand new class, Grocery, that enables us to construct a group of Merchandise together with their portions.

On this case, we are able to use dunder strategies for permitting some commonplace operations like:

  1. Including a particular amount of Merchandise to the Grocery utilizing the + operator
  2. Iterating instantly over the Grocery class utilizing a for loop
  3. Accessing a particular Merchandise from the Grocery class utilizing the bracket [] notation

To attain this, we are going to outline (we already see that a generic class shouldn’t have these strategies by default) the dunder strategies __add__, __iter__ and __getitem__ respectively.

from typing import Non-compulsory, Iterator
from typing_extensions import Self

class Grocery:

def __init__(self, objects: Non-compulsory[dict[Item, int]] = None):
self.objects = objects or dict()

def __add__(self, new_items: dict[Item, int]) -> Self:

new_grocery = Grocery(objects=self.objects)

for new_item, amount in new_items.objects():

if new_item in new_grocery.objects:
new_grocery.objects[new_item] += amount
else:
new_grocery.objects[new_item] = amount

return new_grocery

def __iter__(self) -> Iterator[Item]:
return iter(self.objects)

def __getitem__(self, merchandise: Merchandise) -> int:

if self.objects.get(merchandise):
return self.objects.get(merchandise)
else:
elevate KeyError(f"Merchandise {merchandise} not within the grocery")

Allow us to initialize a Grocery occasion and print the content material of its principal attribute, objects.

merchandise = Merchandise(identify="Milk (1L)", value=0.99)
grocery = Grocery(objects={merchandise: 3})

>>> print(grocery.objects)
{Merchandise('Milk (1L)', 0.99): 3}

Then, we use the + operator so as to add a brand new Merchandise and confirm the modifications have taken impact.

new_item = Merchandise(identify="Soy Sauce (0.375L)", value=1.99)
grocery = grocery + {new_item: 1} + {merchandise: 2}

>>> print(grocery.objects)
{Merchandise('Milk (1L)', 0.99): 5, Merchandise('Soy Sauce (0.375L)', 1.99): 1}

Pleasant and specific, proper?

The __iter__ methodology permits us to loop by a Grocery object following the logic carried out within the methodology (i.e., implicitly the loop will iterate over the weather contained within the iterable attribute objects).

>>> print([item for item in grocery])
[Item('Milk (1L)', 0.99), Item('Soy Sauce (0.375L)', 1.99)]

Equally, accessing components is dealt with by defining the __getitem__ dunder:

>>> grocery[new_item]
1

fake_item = Merchandise("Creamy Cheese (500g)", 2.99)
>>> grocery[fake_item]
KeyError: "Merchandise Merchandise('Creamy Cheese (500g)', 2.99) not within the grocery"

In essence, we assigned some commonplace dictionary-like behaviours to our Grocery class whereas additionally permitting some operations that will not be natively out there for this information sort.

Improve performance: make lessons callable for simplicity and energy.

Allow us to wrap up this deep-dive on dunder strategies with a remaining eample showcasing how they could be a highly effective instrument in our arsenal.

Photograph by Marek Studzinski on Unsplash

Think about we have now carried out a operate that performs deterministic and gradual calculations primarily based on a sure enter. To maintain issues easy, for instance we are going to use an identification operate with a built-in time.sleep of some seconds.

import time 

def expensive_function(enter):
time.sleep(5)
return enter

What occurs if we run the operate twice on the identical enter? Effectively, proper now calculation can be executed twice, which means that we twice get the identical output ready two time for the entire execution time (i.e., a complete of 10 seconds).

start_time = time.time()

>>> print(expensive_function(2))
>>> print(expensive_function(2))
>>> print(f"Time for computation: {spherical(time.time()-start_time, 1)} seconds")
2
2
Time for computation: 10.0 seconds

Does this make sense? Why ought to we do the identical calculation (which ends up in the identical output) for a similar enter, particularly if it’s a gradual course of?

One doable answer is to “wrap” the execution of this operate contained in the __call__ dunder methodology of a category.

This makes cases of the category callable similar to features — which means we are able to use the simple syntax my_class_instance(*args, **kwargs) — whereas additionally permitting us to make use of attributes as a cache to chop computation time.

With this method we even have the pliability to create a number of course of (i.e., class cases), every with its personal native cache.

class CachedExpensiveFunction:

def __init__(self) -> None:
self.cache = dict()

def __call__(self, enter):
if enter not in self.cache:
output = expensive_function(enter=enter)
self.cache[input] = output
return output
else:
return self.cache.get(enter)

start_time = time.time()
cached_exp_func = CachedExpensiveFunction()

>>> print(cached_exp_func(2))
>>> print(cached_exp_func(2))
>>> print(f"Time for computation: {spherical(time.time()-start_time, 1)} seconds")
2
2
Time for computation: 5.0 seconds

As anticipated, the operate is cached after the primary run, eliminating the necessity for the second computation and thus chopping the general time in half.

As above talked about, we are able to even create separate cases of the category, every with its personal cache, if wanted.

start_time = time.time()
another_cached_exp_func = CachedExpensiveFunction()

>>> print(cached_exp_func(3))
>>> print(another_cached_exp_func (3))
>>> print(f"Time for computation: {spherical(time.time()-start_time, 1)} seconds")
3
3
Time for computation: 10.0 seconds

Right here we’re! A easy but highly effective optimization trick made doable by dunder strategies that not solely reduces redundant calculations but in addition gives flexibility by permitting native, instance-specific caching.

My remaining issues

Dunder strategies are a broad and ever-evolving subject, and this writing doesn’t purpose to be an exhaustive useful resource on the topic (for this objective, you may discuss with the 3. Data model — Python 3.12.3 documentation).

My aim right here was moderately to elucidate clearly what they’re and the way they can be utilized successfully to deal with some widespread use instances.

Whereas they will not be necessary for all programmers on a regular basis, as soon as I received an excellent grasp of how they work they’ve made a ton of distinction for me and hopefully they could be just right for you as properly.

Dunder strategies certainly are a solution to keep away from reinventing the wheel. In addition they align carefully with Python’s philosophy, resulting in a extra concise, readable and convention-friendly code. And that by no means hurts, proper?

Source link

#Dunder #Strategies #Hidden #Gems #Python #Federico #Zabeo #Nov

Previous Post

Code found online exploits LogoFAIL to install Bootkitty Linux backdoor

Next Post

Ransomware Gangs Seek Pen Testers to Boost Quality

AiNEWS2025

AiNEWS2025

Next Post
Ransomware Gangs Seek Pen Testers to Boost Quality

Ransomware Gangs Seek Pen Testers to Boost Quality

Stay Connected test

  • 23.9k Followers
  • 99 Subscribers
  • Trending
  • Comments
  • Latest
A tiny new open source AI model performs as well as powerful big ones

A tiny new open source AI model performs as well as powerful big ones

0
Water Cooler Small Talk: The Birthday Paradox 🎂🎉 | by Maria Mouschoutzi, PhD | Sep, 2024

Water Cooler Small Talk: The Birthday Paradox 🎂🎉 | by Maria Mouschoutzi, PhD | Sep, 2024

0
Ghost of Yōtei: The acclaimed Ghost of Tsushima is getting a sequel

Ghost of Yōtei: The acclaimed Ghost of Tsushima is getting a sequel

0
Best Headphones for Working Out (2024): Bose, Shokz, JLab

Best Headphones for Working Out (2024): Bose, Shokz, JLab

0
The science of human touch – and why it’s so hard to replicate in robots

The science of human touch – and why it’s so hard to replicate in robots

2025-12-25
Meet the man hunting the spies in your smartphone

Meet the man hunting the spies in your smartphone

2025-12-25
The Machine Learning “Advent Calendar” Day 24: Transformers for Text in Excel

The Machine Learning “Advent Calendar” Day 24: Transformers for Text in Excel

2025-12-25
Being Santa Claus is a year-round calling

Being Santa Claus is a year-round calling

2025-12-25

Recent News

The science of human touch – and why it’s so hard to replicate in robots

The science of human touch – and why it’s so hard to replicate in robots

2025-12-25
Meet the man hunting the spies in your smartphone

Meet the man hunting the spies in your smartphone

2025-12-25
The Machine Learning “Advent Calendar” Day 24: Transformers for Text in Excel

The Machine Learning “Advent Calendar” Day 24: Transformers for Text in Excel

2025-12-25
Being Santa Claus is a year-round calling

Being Santa Claus is a year-round calling

2025-12-25
Footer logo

We bring you the best Premium WordPress Themes that perfect for news, magazine, personal blog, etc. Check our landing page for details.

Follow Us

Browse by Category

  • AI & Cloud Computing
  • AI & Cybersecurity
  • AI & Sentiment Analysis
  • AI Applications
  • AI Ethics
  • AI Future Predictions
  • AI in Education
  • AI in Fintech
  • AI in Gaming
  • AI in Healthcare
  • AI in Startups
  • AI Innovations
  • AI News
  • AI Research
  • AI Tools & Automation
  • Apps
  • AR/VR & AI
  • Business
  • Deep Learning
  • Emerging Technologies
  • Entertainment
  • Fashion
  • Food
  • Gadget
  • Gaming
  • Health
  • Lifestyle
  • Machine Learning
  • Mobile
  • Movie
  • Music
  • News
  • Politics
  • Review
  • Robotics & Smart Systems
  • Science
  • Sports
  • Startup
  • Tech
  • Travel
  • World

Recent News

The science of human touch – and why it’s so hard to replicate in robots

The science of human touch – and why it’s so hard to replicate in robots

2025-12-25
Meet the man hunting the spies in your smartphone

Meet the man hunting the spies in your smartphone

2025-12-25
  • About
  • Advertise
  • Privacy & Policy
  • Contact

© 2025 JNews - Premium WordPress news & magazine theme by Jegtheme.

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result

© 2025 JNews - Premium WordPress news & magazine theme by Jegtheme.