Нудний вступ я опущу, і перейду зразу до розваги:
def case(func): # декоратор прикладу
print func.__name__ # печатаємо назву
try:
func() # виконуємо функцію
except Exception, e: # Якщо є помилки
print 'Error:', e # помічаємо і продовжуємо
print
@case
def test_a():
x = 1
def inner():
x = 2 # x в цій області імен посилається на новий об’єкт - 2
print 'inner:', x # x == 2
inner()
print 'outer:', x # x == 1. Цю область імен ми не чіпали
@case
def test_b():
x = [1]
def inner():
x[0] = 2 # при обчисленні x[0], ми шукаємо x у всіх просторах тут і вище
print 'inner:', x # x == [2], x посилається на все той же об’єкт, але він змінився
inner()
print 'outer:', x # x == [2], сказано ж, об’єкт змінився.
@case
def test_c():
x = 1
def inner():
x +=1 # генерує UnboundLocalError
# бо x - в лівій частині присвоєння, що робить його локальним.
# а в правій частині - x + 1, значення якого ще не визначено
# бо ж x щойно з’явився в просторі імен
# детальніше про те чому так: http://eli.thegreenplace.net/2011/05/15/understanding-unboundlocalerror-in-python/
print 'inner:', x
inner()
print 'outer:', x # сюди ми не доходимо
# Як реалізувати нелокальну змінну, якщо ви працюємо не з третім Python?
@case
def test_d():
# використати mutable об’єкт
nonlocal = lambda:7 # функція підходить
nonlocal.x = 1
def inner():
nonlocal.x += 1
print 'inner:', nonlocal.x # == 2
inner()
print 'outer:', nonlocal.x # == 2
Мораль теж опущу, все таки потрібно працювати.
Filed under: Кодерство Tagged: Python
