# Coloring a string in a terminal

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


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.

• Hack is fine, as long as you know it is one xD. Its also a means to explore the internals. Mar 16 '16 at 8:55

This is what I came with, it seems to be a much more generic and functional option. Personally, I would also use string formatting to fill color codes in string only when they are needed. Anyway, here is a sample:

def tag(attribute):
attribute = ''.join(('{', attribute, '}'))
endattr = "{ENDC}"

return lambda text: ''.join((attribute, text, endattr))

#Usage
blue = tag("BLUE")
text = blue("It's blue text")
print(text.format(**bcolors))

# or if not using format
blue = tag("\033[94m")
print(blue("It's another blue text"))
# but I find this much less readable


You may also try to achieve a completely custom behaviour by defining a __getattr__ method in a class. However, I don't believe this is complex enough to use it, unless you really need to use single function instance for this.

Sidenote: in Python, string cancatenation with + is inefficient, use ''.join instead.