Как я могу ссылаться на функцию не по имени в ее определении в Python? - PullRequest
3 голосов
/ 28 марта 2012

У меня есть небольшая библиотека полезных функций для взаимодействия с API моей компании, и я натолкнулся (как мне кажется, на этот вопрос) на интересный вопрос, на который я не могу найти ответ.

Мне часто приходится запрашивать большие объемы данных у API, поэтому я делаю что-то вроде:

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

Это отлично работает и позволяет мне перезапустить поиск с того места, где я остановился, если что-то пойдет не так. Однако, поскольку функции python являются обычными объектами, мы можем делать такие вещи, как:

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

и тогда мы можем опросить вас о его свойствах позже, например:

yo.hi => "yo!"

мой вопрос: могу ли я переписать свой пример на основе классов, чтобы закрепить данные в самой функции, не обращаясь к функции по имени. Я знаю, что могу сделать это:

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

но я бы хотел сделать что-то вроде:

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

Можно ли ссылаться на «текущий» объект чем-либо, кроме его имени? Что-то вроде «это», «я» или «мемеме!» это то, что я ищу.

Ответы [ 3 ]

3 голосов
/ 28 марта 2012

Я не понимаю , почему вы хотите это сделать, но это то, что комбинатор с фиксированной точкой позволяет вам делать:

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

Итак, выЗвоните get_data как обычно, и он «волшебным образом» знает, что f означает себя.

2 голосов
/ 28 марта 2012

Вы могли бы сделать это, но (a) данные не для вызова функции, но для функции (b) намного легче достигнуть такого рода вещи с классом.

Если бы у вас былочтобы сделать это, вы можете сделать что-то вроде этого:

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

Лямбда необходима, потому что вам нужно отложить оценку термина ybother до тех пор, пока что-то не будет связано с ним.

Альтернативно, и все более и более бессмысленно:

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)

Или:

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

    return inbothered, inbothered(inbothered)

Эта последняя версия каждый раз предоставляет вам новый объект функции, который вам может понравиться.

Для этого почти наверняка есть интроспективные приемы, но они еще менее полезны.

1 голос
/ 28 марта 2012

Не уверен, что это поможет вам, но как насчет использования декоратора.

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)

ВЫХОД

[1]
[1, 2]
[1, 2, 3]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...