Nishant
Nishant

Reputation: 21934

Use a generic function to do stuff based on the caller?

I have this code which makes it easy to color a string in terminal but it is looking really repetitive. Is there a functional way of doing this more effectively?

It seems really trival, something like strings blue,red etc should point to a generic function, and when you invoke it, you should get the output depending on the caller's name!

But apparently such a thing doesn't exist unless I call it as arguements. But then I lose the flexibility of writing blue(bold(italics("Foo"))) which is really the best way to do this from an end user perspetive.

Can I have a single function object in the memory and do this more effectively?

bcolors = {"BLUE": '\033[94m',
           "HIGH": '\033[93m',
           "OKAY": '\033[92m',
           "FAIL": '\033[91m',
           "BOLD": '\033[1m',
           "LINE": '\033[4m',
           "ENDC": '\033[0m'
           }

def blue(string):
    return bcolors["BLUE"] + string + bcolors["ENDC"]


def yellow(string):
    return bcolors["HIGH"] + string + bcolors["ENDC"]


def green(string):
    return bcolors["OKAY"] + string + bcolors["ENDC"]


def red(string):
    return bcolors["FAIL"] + string + bcolors["ENDC"]


def bold(string):
    return bcolors["BOLD"] + string + bcolors["ENDC"]


def line(string):
    return bcolors["LINE"] + string + bcolors["ENDC"]

Upvotes: 1

Views: 58

Answers (2)

Netwave
Netwave

Reputation: 42796

How about build them on the fly?:

bcolors = {"BLUE": '\033[94m',
           "HIGH": '\033[93m',
           "OKAY": '\033[92m',
           "FAIL": '\033[91m',
           "BOLD": '\033[1m',
           "LINE": '\033[4m',
           "ENDC": '\033[0m'
           }

def _genF(color):
    return lambda s: bcolors[color] + s + bcolors["ENDC"]

globals().update({k.lower():_genF(k) for k,v in bcolors.items()})

In[10]: blue("Foo")
Out[10]: '\x1b[94mFoo\x1b[0m'
In[11]: blue(bold(okay("Foo")))
Out[11]: '\x1b[94m\x1b[1m\x1b[92mFoo\x1b[0m\x1b[0m\x1b[0m'

This way yo can just use the bcolors dict info for boulding all the methods you need just modifiying the dict.

Upvotes: 1

deceze
deceze

Reputation: 522626

A function should never vary its behaviour depending on who called it; only its arguments should influence its behaviour, anything else is madness.

The obvious refactoring to make it dryer here would be something along these lines:

def _format(start, string):
    return bicolors[start] + string + bcolors['ENDC']

def blue(string):
    return _format('BLUE', string)

If you wrap this in a class with some magic properties or method call overrides, you could even start deriving the 'BLUE' parameter from the function call.

Upvotes: 1

Related Questions