def is_even(n):
    if n % 2 == 0:
        print("yea!")
        
    def is_mult_four():
        if n % 4 == 0:
            return "yea, mod4!"
    
    print(is_mult_four())
    print("now in is_even_scope!")

print(is_even(4))

"""
Explanation: Decorators
Decorators are functions that alter the functionality of other functions without explicitly modifying them.
Understanding decorators requires one to understand the scope and objectivity of functions themselves.
Functions inside other Functions
End of explanation
"""


def name_me(name):
    def formal():
        print("Sir {}, welcome!".format(name))
        
    def informal():
        print("Hey my friend!")
    
    if name == "friend":
        return informal
    else:
        return formal

x = name_me("friend")

x()

y = name_me("someone_else")

y()

"""
Explanation: Returning Functions
End of explanation
"""


def is_even(n):
    if n % 2 == 0:
        return ("yes", "even")
    else:
        return ("no", "odd")
    
def sentencify(func):
    print("{}, it's {} mate!".format(func[0], func[1]))

sentencify(is_even(3))

sentencify(is_even(2))

"""
Explanation: Functions as Arguments
End of explanation
"""


def rejection_decorator(func):
    def func_wrapper(name):
        return "Hello {},\n\tWe're sorry to inform about the decision.\n-The Team".format(func(name))
    return func_wrapper

@rejection_decorator
def get_letter(name):
    return name

print(get_letter("John"))

"""
Explanation: Decorator
We're going to show an example of a decorator.
End of explanation
"""


def bold_decorator(func):
    def func_wrapper(some_text):
        return "[b]{}[/b]".format(func(some_text))
    return func_wrapper

def italic_decorator(func):
    def func_wrapper(some_text):
        return "[i]{}[/i]".format(func(some_text))
    return func_wrapper

def underline_decorator(func):
    def func_wrapper(some_text):
        return "[u]{}[/u]".format(func(some_text))
    return func_wrapper

@bold_decorator
@italic_decorator
@underline_decorator
def text(some_text):
    return some_text

print(text("Modify me!"))

"""
Explanation: Multiple Decorators
A function can have multiple decorators, and thus be altered quite a few times. Let's try an example where be implement bold, italics, and underline tags (that don't actually work), but look like they would have.
End of explanation
"""


