How to implement an "Apply" behavior in python
Question:
I’d like to implement an apply()
behavior in a class instance.
by "Apply" i mean, typically realizing a parametric object in place. Meaning that the user might create a parametric object, change it’s settings, and later on, realize the object.
Here is an example on how such an apply behavior would work in the context of a 3D application
my_cube = ParametricCube()
my_cube.height = 2
my_cube.width = 1
my_cube.subdivision = 3
print(type(my_cube),)
>>> <class ParametricCube>
#.. a few moments later
my_cube.make_real() #== apply in place behavior!
print(type(my_cube),)
>>> <class 3D_Object>
The pythonic way to do it, would be to re-assign the variable
instead of using my_cube.make_real()
we would use my_cube = my_cube.make_real()
i am not interested by this solution, we’d like to directly impact the value of my_cube
w/o monkey patching many variable severywhere at runtime
Here is an abstract example, un-related to an 3D app context
class Expression():
"""parametric expression of a+b+c"""
def __init__(self):
#parameters defaults
self.a = 1
self.b = 2
self.c = 3
def __str__(self):
return str(f"<Expression '{self.a}+{self.b}+{self.c}'={self.a + self.b + self.c}>")
def realize(self):
"""apply in place behavior"""
#realize our expression into an int or float somehow?
return None
x = Expression()
x.a = 1
x.b = 1
x.c = 1
print(x)
>>>"<Expression 1+1+1=3>"
print(type(x))
>>> <class Expression>
#apply in place behavior
x.realize()
print(x)
>>>3
print(type(x))
>>> <class 'float'>
Answers:
I’m not sure what are you asking for, but what about this?
class Realized:
def __str__(self):
return str(self.a + self.b + self.c)
class Expression:
"""a+b+c parametric expression"""
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
def __str__(self):
return str(
f"<Expression '{self.a}+{self.b}+{self.c}'={self.a + self.b + self.c}>"
)
def realize(self):
"""apply in place behavior"""
# how to apply self into ??
temp = self
self.__class__ = Realized # Change the type of the object
self.__dict__.update(temp.__dict__) # Copy over data
return None
x = Expression()
x.a = 1
x.b = 1
x.c = 1
print(x)
print(type(x))
x.realize() # apply in place behavior
print(x)
print(type(x))
Output:
$ python test.py
<Expression '1+1+1'=3>
<class '__main__.Expression'>
3
<class '__main__.Realized'>
Here’s an extendable implementation:
from typing import Any
class Realizable:
"""Inherit this to have a class that can be realized"""
"""Private var to hold class type to be realized"""
_realize_class_type: Any
def __init__(self, *args, **kwargs):
self._realize_class_type = kwargs["realizer"]
def realize(self):
"""apply in place behavior"""
temp = self
self.__class__ = self._realize_class_type # Change the type of the object
self.__dict__.update(temp.__dict__) # Copy over data
class ExpressionRealized:
def __str__(self):
return str(self.a + self.b + self.c)
class Expression(Realizable):
"""a+b+c parametric expression"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.a = 1
self.b = 2
self.c = 3
def __str__(self):
return str(
f"<Expression '{self.a}+{self.b}+{self.c}'={self.a + self.b + self.c}>"
)
x = Expression(realizer=ExpressionRealized)
x.a = 1
x.b = 1
x.c = 1
print(x)
print(type(x))
x.realize() # apply in place behavior
print(x)
print(type(x))
I’d like to implement an apply()
behavior in a class instance.
by "Apply" i mean, typically realizing a parametric object in place. Meaning that the user might create a parametric object, change it’s settings, and later on, realize the object.
Here is an example on how such an apply behavior would work in the context of a 3D application
my_cube = ParametricCube()
my_cube.height = 2
my_cube.width = 1
my_cube.subdivision = 3
print(type(my_cube),)
>>> <class ParametricCube>
#.. a few moments later
my_cube.make_real() #== apply in place behavior!
print(type(my_cube),)
>>> <class 3D_Object>
The pythonic way to do it, would be to re-assign the variable
instead of using my_cube.make_real()
we would use my_cube = my_cube.make_real()
i am not interested by this solution, we’d like to directly impact the value of my_cube
w/o monkey patching many variable severywhere at runtime
Here is an abstract example, un-related to an 3D app context
class Expression():
"""parametric expression of a+b+c"""
def __init__(self):
#parameters defaults
self.a = 1
self.b = 2
self.c = 3
def __str__(self):
return str(f"<Expression '{self.a}+{self.b}+{self.c}'={self.a + self.b + self.c}>")
def realize(self):
"""apply in place behavior"""
#realize our expression into an int or float somehow?
return None
x = Expression()
x.a = 1
x.b = 1
x.c = 1
print(x)
>>>"<Expression 1+1+1=3>"
print(type(x))
>>> <class Expression>
#apply in place behavior
x.realize()
print(x)
>>>3
print(type(x))
>>> <class 'float'>
I’m not sure what are you asking for, but what about this?
class Realized:
def __str__(self):
return str(self.a + self.b + self.c)
class Expression:
"""a+b+c parametric expression"""
def __init__(self):
self.a = 1
self.b = 2
self.c = 3
def __str__(self):
return str(
f"<Expression '{self.a}+{self.b}+{self.c}'={self.a + self.b + self.c}>"
)
def realize(self):
"""apply in place behavior"""
# how to apply self into ??
temp = self
self.__class__ = Realized # Change the type of the object
self.__dict__.update(temp.__dict__) # Copy over data
return None
x = Expression()
x.a = 1
x.b = 1
x.c = 1
print(x)
print(type(x))
x.realize() # apply in place behavior
print(x)
print(type(x))
Output:
$ python test.py
<Expression '1+1+1'=3>
<class '__main__.Expression'>
3
<class '__main__.Realized'>
Here’s an extendable implementation:
from typing import Any
class Realizable:
"""Inherit this to have a class that can be realized"""
"""Private var to hold class type to be realized"""
_realize_class_type: Any
def __init__(self, *args, **kwargs):
self._realize_class_type = kwargs["realizer"]
def realize(self):
"""apply in place behavior"""
temp = self
self.__class__ = self._realize_class_type # Change the type of the object
self.__dict__.update(temp.__dict__) # Copy over data
class ExpressionRealized:
def __str__(self):
return str(self.a + self.b + self.c)
class Expression(Realizable):
"""a+b+c parametric expression"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.a = 1
self.b = 2
self.c = 3
def __str__(self):
return str(
f"<Expression '{self.a}+{self.b}+{self.c}'={self.a + self.b + self.c}>"
)
x = Expression(realizer=ExpressionRealized)
x.a = 1
x.b = 1
x.c = 1
print(x)
print(type(x))
x.realize() # apply in place behavior
print(x)
print(type(x))