What often happens in code I'm writing is I'll have a function that checks a condition dependent on many other conditions, e.g.:
def is_foo(bar):
if X: return True
if Y: return False
if Z: return True
return False
Then, I'll want to debug my code or log it, so I'll change the above to:
def is_foo_reason(bar):
if X: return True, "cause of X you fool"
if Y: return False, "no X but Y"
if开发者_如何学Python Z: return True, "Z Z Z Z Z Z"
return False, "default"
#for backwards compatibility:
def is_foo(bar): return is_foo_reason(bar)[0]
Then the code that wants the reason (so it can log it / show it to user, w/e) calls the _reason
version.
My question is: is there any more elegant way to do this?
This is a perfectly good way to do it. Only thing I might change is nest is_foo_reason
in is_foo
(so that there's only one, simple interface) and add a default argument to is_foo()
, e.g.
#for backwards compatibility:
def is_foo(bar, reason=False):
def is_foo_reason(bar):
if X: return True, "cause of X you fool"
if Y: return False, "no X but Y"
if Z: return True, "Z Z Z Z Z Z"
return False, "default"
if reason:
return is_foo_reason(bar)
else:
return is_foo_reason(bar)[0]
That way, the function by default won't give a reason, but if you want one, you can ask for one.
I think you shouldn't change the semantics of your function(s) if it's just about debugging. Use e.g. a logger instead. Take a look at Python's logging module: http://docs.python.org/library/logging.html
import logging
def is_foo(bar):
logger = logging.getLogger()
if X:
logger.debug("msg1")
return True
if Y:
logger.debug("msg2")
...
Then you can define your logging handler to either log the messages to a file, or print them on the screen, etc.
For future extensibility of your return values, use a namedtuple:
from collections import namedtuple
ExplainedValue = namedtuple('ExplainedValue', 'value explanation')
def is_foo_reason(bar):
if X: return ExplainedValue(True, "cause of X you fool")
if Y: return ExplainedValue(False, "no X but Y")
if Z: return ExplainedValue(True, "Z Z Z Z Z Z")
return ExplainedValue(False, "default")
def is_foo(bar): return is_foo_reason(bar).value
精彩评论