Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Is there a way to add extra attributes to a built-in function in python?

Suppose I have a function and want to add extra attributes to it e.g. a ‘last inputted’ attribute to a print statement. This function would be able to take over all existing functionality & some extra functionality.

My idea was to make a function that would have the exact same functionality as a print statement but also be able to remember the last thing outputted.

I made this..

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

last_mes = ""
def pprint(message, **kwargs):
    global last_mes
    print(message, **kwargs)
    last_mes = message

I don’t think this is the best way of doing it though. Is there an optimum way of doing it?

>Solution :

There’s no perfect way, but you could at least avoid polluting the global namespace by attaching the extra data to the function itself:

def pprint(message, **kwargs):
    print(message, **kwargs)
    pprint.last_mes = message
pprint.last_mes = ""

Other solutions include a singleton callable class instance:

class _StatefulPprint:
    def __init__(self):
        self.last_mes = ""
    def __call__(self, message, **kwargs):
        print(message, **kwargs)
        self.last_mes = message
pprint = _StatefulPprint()
# Optionally remove class to remove definition from view:
del _StatefulPprint

or use a closure maker:

def make_pprint():
    last_mes = ""
    def pprint(message, **kwargs):
        nonlocal last_mes
        print(message, **kwargs)
        last_mes = message
    return pprint
pprint = make_pprint()
del make_pprint  # Optional

The closure makes it impractical for you to access last_mes outside pprint though, so for this specific case (where doing so is almost certainly a design goal) it won’t work.

Last option I’ll give is the hackiest one (which shares the weakness of the closure, and adds one more, but is the simple to write); hide it in a mutable default parameter:

def pprint(message, *, _last_mes_store=[""], **kwargs):
    print(message, **kwargs)
    _last_mes_store[0] = message

The extra problem that adds is that if the caller actually passes _last_mes_store by keyword, you don’t update the "function static" default parameter you intended to.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading