Is there a simpler way to write code when you want to define a method that has almost the same functionality for different instance variables, such as the following?
More specifically, add_x()
, add_y()
, add_z()
would be the same method.
Please reply.
class test:
def__init__(self):
self.x = 1
self.y = 2
self.z = 3
default_x(self):
self.x + = 1
default_y(self):
self.y + = 1
default_z(self):
self.z+=1
I tried writing it like this, but it's the same as using the attribute directly (for example, t.x+=1
).
from numbers import Number
class test:
def__init__(self):
self.x = 1
self.y = 2
self.z = 3
default (self, attr):
if attr in vars (self):
v=getattr(self, attr)
if isinstance(v, Number):
setattr(self, attr, v+1)
def__str__(self):
return', '.join(f'{a}:{v}'for a, vinvars(self).items())
if__name__=='__main__':
t = test()
print(t)
t.add('x'), t.add('y'), t.add('z')
print(t)
# execution result
x:1, y:2, z:3
x:2, y:3, z:4
Although it is not the specific requirement of your question, copying functions of almost the same function and rewriting only variable names is not beautiful, contrary to DRY principle.
To avoid this, we want to aggregate common actions into the add
method.
If you have a hidden request that , you can write to DRY using functools.partialmethod
added to version 3.4 or later.
The following sample code creates a __add
function that can only be called within the class, and aggregates the process by calling it from the add_x
function, etc.
This prevents duplication of functions without changing out-of-class code.
from functools import partialmethod
class test:
def__init__(self):
self.x = 1
self.y = 2
self.z = 3
# private function
def__add(self, varname):
setattr(self, varname, getattr(self, varname)+1)
# Define public functions in partialmethod
add_x = partialmethod(__add, 'x')
add_y=partialmethod(__add, 'y')
add_z = partialmethod(__add, 'z')
def__str__(self):
return', '.join(f'{a}:{v}'for a, vinvars(self).items())
t = test()
print(t)
t.add_x()
t.add_z()
print(t)
# execution result
x:1, y:2, z:3
x:2, y:2, z:4
The code presented in the example is just a sample, so the solution may be different from the actual problem case, but since x, y, and z are defined as variables, I thought it was a problem that the method could not dynamically change the target.
If you stop defining variables and keep them in dict, you will be able to change the target dynamically.
class test:
def__init__(self):
self.fields = {"x":1, "y":2, "z":3}
default (self, name):
self.fields [name] + = 1
t = test()
t.add("x")
t.add("y")
t.add("z")
print(t.fields)
Is there a simpler way to write the code?
If you write a decorator that defines a common method, you can simplify the code a little.
*The code to add 1 to the field was based on the code in Metropolis's answer (or rather, it's mostly misused).
# Class decorator to add one method to the field
default_method(cls):
from numbers import Number
default (cls, attr):
if attr in vars (cls):
v=getattr(cls, attr)
if isinstance(v, Number):
setattr(cls, attr, v+1)
cls.add=add
defstr(cls):
return', '.join(f'{a}:{v}'for a, vinvars(cls).items())
cls.__str = str
return cls
@add_method
class test:
def__init__(self):
self.x = 1
self.y = 2
self.z = 3
if__name__=='__main__':
t = test()
print(t)
t.add("x")
t.add("y")
t.add("z")
print(t)
© 2025 OneMinuteCode. All rights reserved.