Как поддерживать списки и словари между вызовами функций в Python? - PullRequest
4 голосов
/ 07 января 2009

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

Предположим, что DIC:

a = {'a':1,'b':2,'c':3}

При первом вызове, скажем, я изменил [a] на 100 Dict становится a = {'a':100,'b':2,'c':3}

При другом вызове я изменил [b] на 200 Я хочу, чтобы этот диск был a = {'a':100,'b':200,'c':3}

Но в моем коде a [a] не остается равным 100. Оно изменяется на начальное значение 1.

Мне нужен ответ как можно скорее .... Я уже опоздал ... Пожалуйста, помогите мне, друзья ...

Ответы [ 7 ]

17 голосов
/ 07 января 2009

Возможно, вы говорите об вызываемом объекте.

class MyFunction( object ):
    def __init__( self ):
        self.rememberThis= dict()
    def __call__( self, arg1, arg2 ):
        # do something
        rememberThis['a'] = arg1
        return someValue

myFunction= MyFunction()

С этого момента используйте myFunction как простую функцию. Вы можете получить доступ к словарю rememberThis, используя myFunction.rememberThis.

15 голосов
/ 07 января 2009

Вы можете использовать статическую переменную :

def foo(k, v):
  foo.a[k] = v
foo.a = {'a': 1, 'b': 2, 'c': 3}

foo('a', 100)
foo('b', 200)

print foo.a
6 голосов
/ 07 января 2009

Если внутри функции создается «а». Это выходит за рамки. Просто создайте его вне функции (и перед вызовом функции). При этом список / хэш не будет удален после того, как программа выйдет из функции.

a = {'a':1,'b':2,'c':3}

# call you funciton here
5 голосов
/ 07 января 2009

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

def function_the_world_sees():
    a = {'a':1,'b':2,'c':3}

    def actual_function(arg0, arg1):
        a[arg0] = arg1
        return a

    return actual_function
stateful_function = function_the_world_sees()

stateful_function("b", 100)    
stateful_function("b", 200)

Главное предостережение, которое следует иметь в виду, заключается в том, что когда вы делаете назначения в "actual_function", они происходят внутри "actual_function". Это означает, что вы не можете переназначить a на другую переменную. Обходное решение, которое я использую, - это поместить все мои переменные, которые я планирую переназначить, либо в один список элементов для каждой переменной, либо в словарь.

3 голосов
/ 08 января 2009

Лично мне нравится идея глобального утверждения. Он не представляет глобальную переменную, но утверждает, что локальный идентификатор фактически ссылается на один в глобальном пространстве имен.

d = dict()
l = list()
def foo(bar, baz):
    global d
    global l
    l.append(bar, baz)
    d[bar] = baz

В python 3.0 есть также «нелокальный» оператор.

3 голосов
/ 07 января 2009

Вы можете «обмануть», используя поведение Python для аргументов по умолчанию. Аргументы по умолчанию оцениваются только один раз; они используются повторно для каждого вызова функции.

>>> def testFunction(persistent_dict={'a': 0}):
...     persistent_dict['a'] += 1
...     print persistent_dict['a']
...
>>> testFunction()
1
>>> testFunction()
2

Это не самое элегантное решение; если кто-то вызывает функцию и передает параметр, он переопределяет значение по умолчанию, что, вероятно, не то, что вам нужно.

Если вам нужен быстрый и грязный способ получить результаты, это сработает. Если вы делаете что-то более сложное, может быть лучше выделить это из класса, подобного упомянутому С. Лотту.

РЕДАКТИРОВАТЬ: переименовал словарь, чтобы он не скрывал встроенный dict в соответствии с комментарием ниже.

2 голосов
/ 08 января 2009

На этот вопрос, на мой взгляд, нет элегантного ответа. Варианты: вызываемые объекты, значения по умолчанию и атрибуты хаков. Вызываемые объекты являются правильным ответом, но они вносят большую структуру для того, что было бы одним «статическим» объявлением на другом языке. Значения по умолчанию - незначительное изменение в коде, но это глупо и может сбить с толку нового программиста на python, смотрящего на ваш код. Мне они не нравятся, потому что их существование не скрыто от тех, кто может смотреть на ваш API.

Я обычно хак с атрибутом. Мой предпочтительный метод:

def myfunct():
    if not hasattr(myfunct, 'state'): myfunct.state = list()
    # access myfunct.state in the body however you want

Сохраняет объявление состояния в первой строке функции, к которой оно принадлежит, а также сохраняет функцию myfunct в качестве функции. Недостатком является то, что вы делаете проверку атрибутов каждый раз, когда вызываете функцию. Это почти наверняка не будет узким местом в большинстве кода.

...