tags:

views:

92

answers:

5

Suppose a function f() returns a value of arbitrary type, perhaps an object but possibly even a builtin type like int or list. Is there a way to assign a variable to that return value, and have a function of my choosing be called the first time the variable is used?

I suppose this is similar to lazy evaluation except that a reference to x exists and can be used by subsequent code.

It might look like this:

x = f() # f is a function, assign variable to return value, but return value is unknown

# do something arbitrary with x
return str(x) # this calls a callback attached to x, which returns the value of x to be used

Again, I want to do this on any type, not just an object instance.

A: 

In that particular case, you can overload the __str__ method on the return type of f(). for example.

def f():
    class _f:
      def __str__(self):
        return "something"
    return _f()
TokenMacGuy
f() is a function call, not a class. and str() is just an example of using x. it could be an arbitrary expression.
Heinrich Schmetterling
+1  A: 

Sounds like you want properties.

class DeepThought(object):

    @property
    def answer(self):
        print ("Computing the Ultimate Answer to the Ultimate Question"
                   " of Life, The Universe, and Everything ")
        return 42

print DeepThought().answer

You can do that only in classes.

THC4k
I want to do this on any type, not just a class. Also, I don't want to call a property on the variable, I just want to pass the variable itself.
Heinrich Schmetterling
Well, I want a pony. Unfortunately, I won't be getting a pony, and cpython doesn't provide a mechanism for doing what you are asking for.
TokenMacGuy
@Token: cpython is an anagram of "thc pony", [cool](http://gallery.8thcivic.com/albums/album03/p1.jpg)!
Nick D
Ill never get that damn pony, always off by a letter or two!
TokenMacGuy
+1  A: 

If you want to write a C extension for it, you could wrap the value in something that behaves the way that Python's weakref.ProxyType does, only with laziness instead of "weak"ness. You can always take a look at the Python source code to see how that's done but something tells me it's nontrivial.

The implementation of the weakref proxy type in Python is here.

Walter Mundt
+1  A: 

Given your constraints, the only viable solution is to fork Python and modify its internal handling of variable lookups. You may also need to modify the bytecode definition. Be prepared for a performance hit.

Or write a PEP and be very, very patient. Your choice.

Mike DeSimone
+1  A: 

There are several implementations of poor-man's lazy evaluation in Python, such as lazypy.

True lazy evaluation is not available in CPython, of course, but is available in PyPy, using the thunk object space.

Piet Delport
What are some other available implementations? lazypy is too slow due to being written in pure python.
Heinrich Schmetterling
Too slow for what purpose? Other implementations are unlikely to be much different, though: this is fundamentally a hackish novelty. If you need this for anything serious, there's probably a better way of doing it.
Piet Delport