How can I refer to a function not by name in its definition in python?

I maintain a small library of useful functions for interacting with my company's APIs, and I ran into (I think) a neat question that I cannot find an answer to.

I often have to request large amounts of data from the API, so I do something like:

class Client(object):
    def __init__(self):
        self.data = []

    def get_data(self, offset = 0):
        done = False
        while not done:
            data = get_more_starting_at(offset)
            self.data.extend(data)
            offset += 1
            if not data:
                done = True

      

This works great and allows me to restart the search where I left off if something went wrong. However, since python functions are regular objects, we can do things like:

def yo():
    yo.hi = "yo!"
    return None

      

and then we can question about its properties later, for example:

yo.hi => "yo!"

      

my question is: can I rewrite my example based on a class to bind data to the function itself without referring to the function by name. I know I can do this:

def get_data(offset=0):
    done = False
    get_data.data = []
    while not done:
        data = get_more_starting_from(offset)
        get_data.data.extend(data)
        offset += 1
        if not data:
            done = True
    return get_data.data

      

but I would like to do something like:

def get_data(offset=0):
    done = False
    self.data = [] # <===== this is the bit I can't figure out
    while not done:
        data = get_more_starting_from(offset)
        self.data.extend(data) # <====== also this!
        offset += 1
        if not data:
            done = True
    return self.data # <======== want to refer to the "current" object

      

Can you refer to the "current" object by anything other than its name? Something like "this", "self", or "memememe!" this is what I am looking for.

+3


source to share


3 answers


I don't understand why you want to do this, but this is what the fixed point combinator allows you to do:

import functools

def Y(f):
    @functools.wraps(f)
    def Yf(*args):
        return inner(*args)
    inner = f(Yf)
    return Yf

@Y
def get_data(f):
    def inner_get_data(*args):
        # This is your real get data function
        # define it as normal
        # but just refer to it as 'f' inside itself
        print 'setting get_data.foo to', args
        f.foo = args
    return inner_get_data

get_data(1, 2, 3)

print get_data.foo

      



Thus, you call get_data

as usual, and he "magically" knows what f

himself means.

+3


source


You could do it, but (a) the data is not meant for every function, and for every function (b) it is much easier to achieve this kind of thing with a class.

If you needed to do this, you can do something like this:

def ybother(a,b,c,yrselflambda = lambda: ybother):
    yrself = yrselflambda()
    #other stuff

      

The lambda is necessary because you need to defer evaluating a term ybother

until something is related to it.

Alternatively, and increasingly pointless:



from functools import partial
def ybother(a,b,c,yrself=None):
    #whatever
    yrself.data = [] # this will blow up if the default argument is used
    #more stuff

bothered = partial(ybother, yrself=ybother)

      

Or:

def unbothered(a,b,c):
    def inbothered(yrself):
        #whatever
        yrself.data = []

    return inbothered, inbothered(inbothered)

      

This latest version provides you with different functional objects every time, which you might like.

There are almost certainly introspective tricks for this, but they are even less useful.

+2


source


Not sure if this does it the way you do, but what about using a decorator.

import functools

def add_self(f):
    @functools.wraps(f)
    def wrapper(*args,**kwargs):
        if not getattr(f, 'content', None):
            f.content = []
        return f(f, *args, **kwargs)
    return wrapper

@add_self
def example(self, arg1):
    self.content.append(arg1)
    print self.content


example(1)
example(2)
example(3)

      

OUTPUT

[1]
[1, 2]
[1, 2, 3]

      

+1


source