HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Coloring a string in a terminal

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
stringcoloringterminal

Problem

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

It seems really trivial, 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 arguments. 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 perspective.

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"]

Solution

I came up with this:

for key in bcolors:
    locals().update({key: lambda string: bcolors[key] + string + bcolors["ENDC"]})


which is almost equivalent to your code (except the function names are uppercase). There is still a function being created for every colour but it's more concise in writing.

It works for me but apparently changing locals() is a bad idea:


Others have suggested assigning to locals(). This won't work inside a function, where locals are accessed using the LOAD_FAST opcode, unless you have an exec statement somewhere in the function.

https://stackoverflow.com/questions/8028708/dynamically-set-local-variable-in-python


Note: The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.

https://docs.python.org/2/library/functions.html#locals

Another way I see is to write a function like so:

def _(color):
    return lambda string: bcolors[color] + string + bcolors[color]


but you'd have to call it like this:

_("BLUE")("hello")


That's the closest I can come up with.

Code Snippets

for key in bcolors:
    locals().update({key: lambda string: bcolors[key] + string + bcolors["ENDC"]})
def _(color):
    return lambda string: bcolors[color] + string + bcolors[color]
_("BLUE")("hello")

Context

StackExchange Code Review Q#122893, answer score: 7

Revisions (0)

No revisions yet.