Reputation: 95
I have this class in which a variable c is used as a intermediate step of the operate() method.
class DumbAdder():
def __init__(self, a : float, b : float):
super(DumbAdder, self).__init__()
self.a = a
self.b = b
def operate(self):
c = self.a
for step in range(self.b):
c = c + 1
result = c
print(result)
After creating the object x by calling DumbAdder with arguments a, b, and calling operate(), we obtain a result which is the sum of the two arguments.
x = DumbAdder(10,20)
x.operate()
In this case we get 30 printed on the screen as a result.
now, let's say we have a new instance y
y = DumbAdder(5,10)
Now, my question: Is there a way to access the values of c in y, when calling operate(), for each step of the for loop, that is, to display 6,7,8...13,14,15 without modifying the definition of operate()? or with minimal modifications
My goal is to be able to switch between a 'normal mode' and a 'debug mode' for my classes with iterations inside the methods. The debug mode would allow me to inspect the evolution of the intermediate values.
NOTE
While writing the question I came up with this solution. I post the question in case someone wants to share a more efficient or elegant way.
class DumbAdder():
def __init__(self, a : float, b : float):
super(DumbAdder, self).__init__()
self.a = a
self.b = b
self.mode = 'normal'
self.c_history = []
def store_or_not(self, c):
if self.mode == 'normal':
pass
elif self.mode == 'debug':
self.c_history.append(c)
def operate(self):
c = self.a
for x in range(self.b):
c = c + 1
self.store_or_not(c)
result = c
print(result)
Upvotes: 0
Views: 55
Reputation: 531693
The typical way to handle this is to log the value, e.g. using the logging
module.
def operate(self):
logger = logging.getLogger("operate")
c = self.a
for x in range(self.b):
c = c + 1
logger.debug(c)
result = c
print(result)
What logging.debug
does is not operate
's concern; it's just a request to do something. What that something is defined the logger's configuration and the handler(s) attached to the logger. Your application can do that without modifying your code at all, since all loggers live in a single application-wide namespace. For example,
# Only log errors by default...
logging.basicConfig(level=logging.ERROR)
# ... but log debugging information for this particular logger
logging.getLogger("operate").setLevel(logging.DEBUG)
This uses the same logging configuration for every instance of DumbAdder
, rather than allowing per-instance debugging. I suspect that's all you really need, but if not, you can have __init__
create an instance specific logger and configure it at that time.
def __init__(self, a, b, debug=False):
super().__init__()
self.a = a
self.b = b
self.logger = logging.getLogger(f'{id(self)}') # Logger specific to this object
if debug:
self.logger.setLevel(logging.DEBUG)
def operate(self):
c = self.a
for x in range(self.b):
c = c + 1
self.logger.debug(c)
result = c
print(result)
Handlers can do much more than simply write to the screen. The default handler created by logging.basicConfig
writes to standard error, but the logging.handler
module provides for writing to files, syslog
, sockets, SMTP servers for e-mail, HTTP services, etc, and you can always write your own handlers to do really whatever you want with the message that the debug
method constructs from the value of c
it receives.
Upvotes: 1