5.3. Decorator Function with Cls¶
5.3.1. Rationale¶
mydecorator
is a decorator nameMyClass
is a class name
- Syntax:
@mydecorator class MyClass: ...
- Is equivalent to:
MyClass = mydecorator(MyClass)
5.3.2. Syntax¶
mydecorator
is a decorator nameMyClass
is a class name
Definition:
def decorator(cls):
class Wrapper(cls):
def __new__(cls, *args, **kwargs):
...
return Wrapper
def decorator(cls):
def wrapper(*args, **kwargs):
instance = cls.__new__(cls, *args, **kwargs)
return instance
return wrapper
Decoration:
@decorator
class MyClass:
...
Usage:
my = MyClass()
5.3.3. Example¶
def run(cls):
def wrapper(*args, **kwargs):
instance = cls.__new__(cls, *args, **kwargs)
return instance
return wrapper
@run
class Astronaut:
def hello(self, name):
return f'My name... {name}'
astro = Astronaut()
astro.hello('José Jiménez')
# 'My name... José Jiménez'
5.3.4. Use Case¶
Logger:
import logging
def logger(cls):
class Wrapper(cls):
logger = logging.getLogger(cls.__name__)
return Wrapper
@logger
class Astronaut:
pass
print(Astronaut.logger)
# <Logger Astronaut (WARNING)>
Object Birthday:
from time import time
def since(cls):
class Wrapper(cls):
_instance_created = time()
return Wrapper
@since
class Astronaut:
pass
print(Astronaut._instance_created)
# 1607187641.3407109
Singleton using functional wrapper:
def singleton(cls):
def wrapper(*args, **kwargs):
if not hasattr(cls, '_instance'):
instance = object.__new__(cls, *args, **kwargs)
setattr(cls, '_instance', instance)
return getattr(cls, '_instance')
return wrapper
@singleton
class DatabaseConnection:
def connect(self):
print(f'Connecting... using {self._instance}')
a = DatabaseConnection() # Creating instance
a.connect()
# Connecting... using <__main__.DatabaseConnection object at 0x10cd56fa0>
b = DatabaseConnection() # Reusing instance
b.connect()
# Connecting... using <__main__.DatabaseConnection object at 0x10cd56fa0>
Singleton using class wrapper:
def singleton(cls):
class Wrapper(cls):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
instance = object.__new__(cls, *args, **kwargs)
setattr(cls, '_instance', instance)
return getattr(cls, '_instance')
return Wrapper
@singleton
class DatabaseConnection:
def connect(self):
print(f'Connecting... using {self._instance}')
a = DatabaseConnection() # Creating instance
a.connect()
# Connecting... using <__main__.singleton.<locals>.Wrapper object at 0x1085b6fa0>
b = DatabaseConnection() # Reusing instance
b.connect()
# Connecting... using <__main__.singleton.<locals>.Wrapper object at 0x1085b6fa0>