2

While playing around with icecream I programmed the following lines of code

if __debug__:
    try:
        from icecream import ic
        ic.configureOutput(includeContext=True)
    except ImportError:  # Graceful fallback if IceCream isn't installed.
        ic = lambda *a: None if not a else (a[0] if len(a) == 1 else a)  # noqa
else:
    ic = lambda *a: None if not a else (a[0] if len(a) == 1 else a)  # noqa

As you can see I want to assign the (same) lambda expression to ic in both cases

  1. if not debugging the code or
  2. if importing icecream is not working

I was wondering if there is a (maybe pythonic) way to handle that idea without redundancy.

Bastian Ebeling
  • 1,138
  • 11
  • 38
  • 4
    `ic = lambda ...` `if not __debug__: try: import ... except ImportError: pass`…? – deceze Apr 06 '21 at 12:54
  • Thanks @deceze , this " overwriting" the `ic`-definition is a nice idea, but not that pythonic, isn't it? – Bastian Ebeling Apr 06 '21 at 12:57
  • 1
    Why wouldn't it be? – deceze Apr 06 '21 at 12:58
  • @deceze I think redefining/overwriting is somehow unclean. But it is just a personal feeling. Indeed your suggestion fulfills my requierment and thus it is good. If no further solution comes up, I'll accept it of course as your answer (if you like to write it that way). Or I'll mention you by self answering. – Bastian Ebeling Apr 06 '21 at 13:03
  • @deceze I added [an answer](https://stackoverflow.com/a/66993603/4518341) based on your comment, thanks! LMK if there's anything you'd want to add. – wjandrea Apr 07 '21 at 20:23

2 Answers2

4

You could define a default, then override it later as needed. I would also add comments to make it clear.

def ic(*a):  # May be overridden later
    if not a:
        return None
    return a[0] if len(a) == 1 else a


if __debug__:
    try:
        from icecream import ic  # Override default
    except ImportError:
        pass  # Fallback to default
    else:
        ic.configureOutput(includeContext=True)

By the way:

  • Named lambdas are bad practice. Use a def instead.
  • I rewrote the function to avoid a double-conditional-expression for better readability.
  • Try to put as little in a "try" clause as necessary, and use else to define what should happen if the try succeeds.

This is based on deceze's comment

wjandrea
  • 28,235
  • 9
  • 60
  • 81
  • 2
    I would add an inline comment directly next to the import that makes it 200% clear that the override is intended. Over time/after refactoring this connection might get lost otherwise. – ojdo Apr 08 '21 at 08:58
  • 1
    I recommend ` # noqa: F811 - no redefinition-error` in the icecream-import-line as this is the corresponding warning (c. f. [flake8](https://www.flake8rules.com/rules/F811.html)) @ojdo – Bastian Ebeling Apr 08 '21 at 14:01
  • 1
    With all that refactoring, this could have been a candidate for codereview.SX :D – ojdo Apr 08 '21 at 15:19
0

A slight variation on the pattern suggested by deceze in the comments:

# file my_icecream.py:
def ic(*a):
    """Icecream fallback implementation"""
    if not a:
        return None
    elif len(a) == 1:
        return a[0]
    else:
        return a
# original file
if not __debug__:
    from my_icecream import ic
else:
    try:
        from icecream import ic
        ic.configureOutput(includeContext=True)
    except ImportError:
        from my_icecream import ic
ojdo
  • 8,280
  • 5
  • 37
  • 60
  • 1
    Thanks, looks interesting. Just a question: Why do you _invert_ the if clause? Is there a bigger sense ? And further - in `my_icecream.py` why do you expand the one-liner? – Bastian Ebeling Apr 07 '21 at 10:06
  • 3
    Both were pure stylistic choices: the breakup of the "oneliner" looks more readable to me, whenever one needs to grasp/modify/adapt it later; but for most purposes, its implementation could/should be as opaque as the `icecream` import hopefully is. – ojdo Apr 07 '21 at 11:16
  • 2
    As for inverting `not __debug__`: I found it cleaner to have the default/production case first, but I could be easily convinced to stay with the order you posted. – ojdo Apr 07 '21 at 11:18