Without advanced constructs like generator, list-comprehension or similar.
Understanding the asterisk (unpacking) and tuples
First we need to understand that *args
is a parameter named args
defined as varargs (multiple parameters as tuple). See
What does ** (double star/asterisk) and * (star/asterisk) do for parameters?
See also this answer which explains it very well:
Using *args
in the function signature packs all of the positional arguments into a single tuple args. If you then say *args
in another function call within your the function body, it spreads it back into multiple arguments, [..]
Why it is used here?
This is used in your function definition def print(*args, **kw):
to mimic the same signature (parameters) as the built-in print
function, originally in Python. With the re-definition _print = print
before this can be seen as interceptor.
The effect will be a print
function that automatically highlights words or output using ANSI-colors (ANSI-escape code) when certain keyword (here "CommandGeek" found).
Your task
Implement the comments (tasks) inside the function body:
#color the word "CommandGeek" green
# locate the word
# surround it with ANSI-color code
#Color entire the message green if "CommandGeek:" is in it.
# locate the word
# surround the entire message with ANSI-color code
Your input (the message(s) containing words or commands) is given by parameter *args
which we know is to pack all positional arguments into a tuple (varargs). The tuple is named args
.
GREEN = "\u001b[32;1m"
RESET = "\u001b[0m"
WORD = "CommandGeek"
# a testable function with debug-prints
def color(*args):
print(len(args))
colored = []
for a in args:
s = str(a)
if s.__contains__(WORD):
print("Found it in: " + s)
colored.append(s.replace(WORD, f"{GREEN}{WORD}{RESET}"))
else:
colored.append(a)
return colored
colored = color('Hello', 'World', 'CommandGeek')
print(colored) # prints the list or tuple (not colored)
print(*colored) # prints all with color if found (because unpacked)
Prints (bold was originally green in console):
3
Found it in: CommandGeek
Hello World CommandGeek
Now we have one word colored.
Next let's color the entire message (= all args) if at least one contains the word.
GREEN = "\u001b[32;1m"
RESET = "\u001b[0m"
WORD = "CommandGeek"
def contains_word(*args):
for a in args:
s = str(a)
if s.__contains__(WORD):
return True
return False
tuple = ('Hello', 'World', 'CommandGeek') # define a tuple
should_color = contains_word(*tuple) # unpack a tuple as multiple args (varargs)
if should_color:
print(GREEN, *tuple, RESET) # prints all elements in color (unpacked)
else:
print(*tuple) # prints the tuple (unpacked, not colored)
Prints (bold was originally green in console):
** Hello World CommandGeek**
Update: complete solution (fixed leading space)
GREEN = "\u001b[32;1m"
RESET = "\u001b[0m"
KEYWORD = "CommandGeek"
def color_word(*args):
colored = []
for a in args:
if isinstance(a, str):
colored.append(a.replace(KEYWORD, f"{GREEN}{KEYWORD}{RESET}"))
else:
colored.append(a)
return colored
print(*color_word('Hello', 1, 'World', True, '_CommandGeek_'))
def contains_word(*args):
for a in args:
if str(a).__contains__("CommandGeek"):
return True
return False
def color_message(*args):
if contains_word(*args): # unpack a tuple as multiple args (varargs)
# surround tuples with color-code and reset-code
colored = (f"{GREEN}{args[0]}",) + args[1:] # prepend to first element (new colored tuple)
colored = colored[0:-1] + (f"{colored[-1]}{RESET}",) # and append on last element (replace colored tuple)
return colored
return args
print(*color_message('Hello', 1, 'World', True, '_CommandGeek_'))
print(*color_message('Hello: CommandGeek'))
Prints on a console supporting ANSI-colors:

Further reading