I want to make it so that before executing the method of the class instance, another mandatory method was carried out:
class Example:
def __init__(self, x, y):
self.x = x
self.y = y
def method_before(self):
print(f"x = {self.x}, y = {self.y}")
def sum_numbers(self):
self.method_before()
print(self.x + self.y)
def mult_numbers(self):
self.method_before()
print(self.x * self.y)
test_instance = Example(x=10, y=2)
test_instance.sum_numbers()
This is simplified example. How can I make the method method_before() run automatically without explicitly specifying it in other methods? Thank you if you share the ways
Here are three potential paths forward. Unfortunately, none of them are completely free of "additional specifications". Note I renamed method_before()
to flag it as "non-public" and make excluding it with the dunder methods more convenient.
Conventional Decorator:
class Example():
def __init__(self, x, y):
self.x = x
self.y = y
@staticmethod
def _method_before(f):
def wrapper(self, *args, **kwargs):
print(f"x = {self.x}, y = {self.y}")
return f(self, *args, **kwargs)
return wrapper
@_method_before
def sum_numbers(self):
print(self.x + self.y)
@_method_before
def mult_numbers(self, z):
print(self.x * self.y * z)
Post Definition Decorator:
class Example():
def __init__(self, x, y):
self.x = x
self.y = y
@staticmethod
def _method_before(f):
def wrapper(self, *args, **kwargs):
print(f"x = {self.x}, y = {self.y}")
return f(self, *args, **kwargs)
return wrapper
def sum_numbers(self):
print(self.x + self.y)
def mult_numbers(self, z):
print(self.x * self.y * z)
method_list = [f for f in dir(Example) if callable(getattr(Example, f)) and not f.startswith("_")]
for m in method_list:
setattr(Example, m, getattr(Example, "_method_before")(getattr(Example, m)))
MetaClass:
class Example_Meta(type):
def __init__(self, name, bases, dict):
method_list = [f for f in dir(self) if callable(getattr(self, f)) and not f.startswith("_")]
for m in method_list:
setattr(self, m, getattr(self, "_method_before")(getattr(self, m)))
class Example(metaclass=Example_Meta):
def __init__(self, x, y):
self.x = x
self.y = y
@staticmethod
def _method_before(f):
def wrapper(self, *args, **kwargs):
print(f"x = {self.x}, y = {self.y}")
return f(self, *args, **kwargs)
return wrapper
def sum_numbers(self):
print(self.x + self.y)
def mult_numbers(self, z):
print(self.x * self.y * z)
All versions should allow you to do:
foo = Example(1, 2)
foo.sum_numbers()
foo.mult_numbers(10)
x = 1, y = 2
3
x = 1, y = 2
20