Уведомления

Группа в Telegram: @pythonsu

#1 Окт. 19, 2010 12:11:46

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

Окружение в замыкании

Может кто объяснить? Следующий код:

class CategoryWidget(forms.CheckboxSelectMultiple):

def render(self, name, value, attrs=None, choices=()):
final_attrs = self.build_attrs(attrs, name=name)
output = [u'<ul>']
print 1, locals()

def render_list(choices):
print 2, locals()
for i, (option_value, option_label, children) in enumerate(choices):
final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
label_for = u' for="%s"' % final_attrs['id']
cb = forms.CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
option_value = force_unicode(option_value)
rendered_cb = cb.render(name, option_value)
option_label = conditional_escape(force_unicode(option_label))
output.append(u'<li><label%s>%s %s</label></li>' % (label_for, rendered_cb, option_label))

render_list(chain(self.choices, choices))
output.append(u'</ul>')
return mark_safe(u'\n'.join(output))
выводит:

1 {'name': ‘sectors’, ‘self’: <zondir.base.forms.CategoryWidget object at 0x91512cc>, ‘value’: None, ‘choices’: (), ‘attrs’: {'id': u'id_sectors'}, ‘output’: , ‘final_attrs’: {'name': ‘sectors’, ‘id’: u'id_sectors'}}
2 {'output': , ‘attrs’: {'id': u'id_sectors'}, ‘name’: ‘sectors’, ‘choices’: <itertools.chain object at 0x91d9ccc>}
Почему внутри вложенной функции доступно output, но недоступно final_attrs?



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Офлайн

#2 Окт. 19, 2010 15:40:35

shupg
От:
Зарегистрирован: 2009-08-07
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

Окружение в замыкании

Упрощенный код

def g():
a = [2]
print locals()

def f():
print locals()
a.append(a)
print locals()
f()

g()
->{'a': }
{'a': }
{'a': [2, ]}

def g():
a = [2]
print locals()

def f():
print locals()
a = 3
print locals()

f()

g()
->{'a': }
{}
{'a': 3}

Разница удивила, но почему оно так работает!



Отредактировано (Окт. 19, 2010 15:41:45)

Офлайн

#3 Окт. 19, 2010 15:58:36

Zubchick
От:
Зарегистрирован: 2009-07-08
Сообщения: 613
Репутация: +  0  -
Профиль   Отправить e-mail  

Окружение в замыкании

shupg
Упрощенный код
в первом случае ‘а’ не находится в локальном окружении и ищется выше. Во втором случае ‘а’ не находится в локальном окружении, после чего создается в нем и имя ‘a’ связывается с 3. В первом случае список ‘а’ не создается внутри функции, потому что чтобы обратиться к методу объекта (список) нужно его сначала создать.



Офлайн

#4 Окт. 19, 2010 16:12:31

shupg
От:
Зарегистрирован: 2009-08-07
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

Окружение в замыкании

Zubchick
Спасибо за ответ.
Уточню вопрос

def g():
a = [2]
def f():
print a
f()
g()
->

def g():
a = [2]
def f():
del a
f()
g()
->UnboundLocalError: local variable ‘a’ referenced before assignment

Почему в одном случае
Zubchick
не находится в локальном окружении и ищется выше
, а в другом нет?



Офлайн

#5 Окт. 19, 2010 17:10:08

Zubchick
От:
Зарегистрирован: 2009-07-08
Сообщения: 613
Репутация: +  0  -
Профиль   Отправить e-mail  

Окружение в замыкании

Наверно что бы функции расположенные внутри по возможности не влияли на внешние, так как это во-первых ужасно читается, во вторых ведет к ошибкам. Чтобы что-то поменять, передавайте это параметром и возвращайте return'ом, это правильный путь. Ну или в случае с замыканиями, параметром можно не передавать.



Офлайн

#6 Окт. 19, 2010 17:52:25

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

Окружение в замыкании

И все таки, почему final_attrs отсутствует в замыкании? Я специально весь кусок кода привел - может я просто не вижу явного косяка?



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Офлайн

#7 Окт. 19, 2010 18:24:11

o7412369815963
От:
Зарегистрирован: 2009-06-17
Сообщения: 1986
Репутация: +  32  -
Профиль   Отправить e-mail  

Окружение в замыкании

PooH
И все таки, почему final_attrs отсутствует в замыкании? Я специально весь кусок кода привел - может я просто не вижу явного косяка?
видимо в этом:
> final_attrs = dict(final_attrs, id='%s_%s' % (attrs, i))

Офлайн

#8 Окт. 19, 2010 21:00:32

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

Окружение в замыкании

PooH
И все таки, почему final_attrs отсутствует в замыкании? Я специально весь кусок кода привел - может я просто не вижу явного косяка?
Разница между output и final_attrs в вашем коде только в том, что final_attrs присваивается значение, а output меняется. То есть final_attrs воспринимается как новая переменная в контексте замыкания, а output - как уже существующая из внешнего контекста.

Вот вам пример:
def foo():
var1 = []
var2 = []
print 1, locals()

def closure1():
print 2, locals()
var1.append(1)
var2 = []

def closure2():
print 3, locals()
var1 = []
var2.append(1)

closure1()
closure2()

foo()
и его результат:
1 {'var1': , ‘var2’: }
2 {'var1': }
3 {'var2': }



Отредактировано (Окт. 19, 2010 21:01:13)

Офлайн

#9 Окт. 20, 2010 03:45:05

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

Окружение в замыкании

Спасибо всем. Понял. А питон-то все таки опасная змеюка, может цапнуть иногда ;)



Вот здесь один из первых отарков съел лаборанта. Это был такой умный отарк, что понимал даже теорию относительности. Он разговаривал с лаборантом, а потом бросился на него и загрыз…

Офлайн

#10 Окт. 21, 2010 00:29:27

Ferroman
От:
Зарегистрирован: 2006-11-16
Сообщения: 2759
Репутация: +  1  -
Профиль   Отправить e-mail  

Окружение в замыкании

В “Python Essential Reference, Fourth Edition” хорошо такие моменты высветлены.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version