Lazily Define Functions in Python

83 views Asked by At

This is more of a theoretical than practical question. In Python, we can do this very ugly thing:

import inspect
import re


class A(object):
  def __init__(self, *args, **kwargs):
    super(A, self).__init__(*args, **kwargs)
    self._name_cache = {}
    # Still want to be able to do proper lookups.
    self._old_get = self.__getattr__

  def __getattr__(self, n, *args, **kwargs):
    # Gets the name of the most local reference.
    frame = inspect.currentframe().f_back
    tmp = frame.f_locals.items() + frame.f_globals.items()
    for k, var in tmp.items():
      if isinstance(var, self.__class__):
        if var is self:
          name = k
          break
        else:
         assert 'Life' == 'Bad'
    patt = re.compile(r'^add_(\d+)$')
    if patt.search(n):
      # Add to the cached functions and return new "attribute."
      if n not in self._name_cache:
          exec('def %s(n):\n  return %s + n' % (n, patt.sub(r'\1', n)))
          exec('%s._name_cache["%s"] = %s' % (name, n, n))
          exec('print "Is it there? %s"' % str(n in self._name_cache))
        return self._name_cache[n]
      else:
        return self._old_get(n, *args, **kwargs)


a = A()
print a.add_2(3)  # Prints 5

There's probably a cleaner solution to this using metaclasses, but I'm not sure I would be able to whip it up. In any case, we did something that looks syntactically like lazy, on-the-fly member function generation.

I have two questions:

  1. I am now wondering whether there is a way I could do this globally. I would just monkey-patch inspect.current_frame().f_globals's get() method, but its attributes are read-only. Is there an interpreter-writable function governing lookup of top-level defed functions?

  2. What other depraved things can one do with the inspect module?

0

There are 0 answers