On classes/methods that work with several properties, what's the best or more pythonic way to work with default parameters (on object instantiation) and overwrite those defaults on calls to that object's methods?
I'd like to be able to create an object with a set of default parameters (being a large amount of possible parameters) and then, when calling that object's methods, either use those default parameters or be able to easily overwrite any of them in the method call.
I have it already working (example below) but I'd like to know what's the most pythonic way to do it.
Let's illustrate my question:
Class definition:
class SimpleInputText:
def __init__(self, basicFont, **kwargs):
self._basicFont = basicFont
self.text = ''
self.set_defaults(**kwargs)
def set_defaults(self, **kwargs):
self.default_text = kwargs.get('default_text', '')
self.color = kwargs.get('color', (0, 0, 0))
self.inactive_color = kwargs.get('inactive_color', (50, 50, 50))
self.error_color = kwargs.get('error_color', None)
self.background_color = kwargs.get('background_color', None)
self.border_color = kwargs.get('border_color', (0, 0, 0))
self.border_size = kwargs.get('border_size', 0)
self.border_radius = kwargs.get('border_radius', 0)
self.padding_left = kwargs.get('padding_left', 0)
self.padding_top = kwargs.get('padding_top', 0)
self.padding = kwargs.get('padding', 2)
self.shadow_offset = kwargs.get('shadow_offset', 0)
self.shadow_color = kwargs.get('shadow_color', (0, 0, 0))
# (and more possible properties)
def input_modal(self, x, y, default_text='', color=None, background_color=None,
inactive_color=None, border_color=None, border_size=None,
border_radius=None, padding_left=None, padding_top=None, padding=None,
shadow_offset=None, shadow_color=None, etc... ):
# Set specific values if passed, otherwise use defaults
cursor_char = self.cursor_char if cursor_char is None else cursor_char
input_type = self.input_type if input_type is None else input_type
check_type = self.check_type if check_type is None else check_type
color = self.color if color is None else color
inactive_color = self.inactive_color if inactive_color is None else inactive_color
inactive_border_color = self.inactive_border_color if inactive_border_color is None else inactive_border_color
error_color = self.error_color if error_color is None else error_color
background_color = self.background_color if background_color is None else background_color
border_color = self.border_color if border_color is None else border_color
border_size = self.border_size if border_size is None else border_size
padding_left = self.padding_left if padding_left is None else padding_left
padding_top = self.padding_top if padding_top is None else padding_top
padding = self.padding if padding is None else padding
border_radius = self.border_radius if border_radius is None else border_radius
shadow_offset = self.shadow_offset if shadow_offset is None else shadow_offset
shadow_color = self.shadow_color if shadow_color is None else shadow_color
# etc...
# the method uses, from now on, the local versions of the variables
# (i.e. color and not self.color) to do its work.
This way I can instantiate an inputBox object with specific values and overwrite any of these values in the moment of calling input_modal()
.
I also considered the possibility of using a dict
for self.defaults
and then get a merge of the defaults and the parameters:
def input_modal(self, x, y, default_text='', **kwargs ):
params = dict(**self.defaults, **kwargs)
# now use params.color, params.border_size, etc in the method
I'm not sure what's the best approach for this specific use-case (allowing defaults and having a large number of possible parameters due to styling options).