LINUX.ORG.RU

[python] Можно как-то культурно использовать атрибуты функции внутри def?

 


0

2

Есть такая конструкция:

def foo(x):
    a = b = 0
    def bar(i):
        ...

    for i in x:
        bar(i)

    print a, b

Внутри bar нужно изменять a и b, но это не возможно.

Решил попробовать использовать атрибуты. Пример:

In [1]: def testatr(x):
   ...:     testatr.a += x
   ...:     
   ...:     

In [2]: testatr.a = 10

In [3]: testatr(10)

In [4]: testatr.a
Out[4]: 20

Тут есть проблема:

In [5]: tatr = testatr

In [6]: testatr = 0

In [7]: tatr(10)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)

/home/glitch/<ipython console> in <module>()

/home/glitch/<ipython console> in testatr(x)

AttributeError: 'int' object has no attribute 'a'

Может есть какой-то способ обратиться к атрибутам этой функции внутри def? Честно говоря, я рассчитывал на что-нибудь типа self, но найти не смог.


В Python 2.x культурно - невозможно. Обычно делается кладж в стиле:

def foo():
  class bar:
    a = 0
  def blarg():
    bar.a = 1
  blarg()

В Python 3.x (и, может быть, 2.7) есть ключевое слово nonlocal.

Кладжа с использованием атрибутов функции не встречал.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Сейчас у меня где-то так:

class Bar(object):
    def __init__(self):
        a = b = 0
    def doBar(i)
        ...

def foo(x):
    bar = Bar()
    for i in x:
        bar(i)
    print bar.a, bar.b

Да, пожалуй стоит убрать класс внутрь. Спрашиваю уже из спортивного интереса.

Изначально это было реализовано именно через объект. Потом захотелось упростить.

g1itch
() автор топика
Ответ на: комментарий от baverman

Тут я понял, что у меня большой пробел в знании языка.

Это работает!

In [4]: def foo(x):
   ...:     e = [0,0]
   ...:     def bar(i):
   ...:         if i > e[0]: e[0] = i
   ...:         if i < e[1]: e[1] = i
   ...:     for i in x:
   ...:         bar(i)
   ...:     print e[0], e[1]
   ...:     
   ...: 

In [5]: foo([1, 2,3,-4,5, -9, -1])
5 -9

Спасибо. А с атрибутами, похоже, тупик и запутывание кода.

g1itch
() автор топика
Ответ на: комментарий от baverman

Да это пример. Переменная с накоплением у меня используется потому что я не могу получить ничего ни из bar, ни из цикла - там используется twisted.internet.task.coiterate.

g1itch
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.