Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 4, 2009 22:15:28

pasaranax
От:
Зарегистрирован: 2009-06-13
Сообщения: 574
Репутация: +  0  -
Профиль   Отправить e-mail  

UnboundLocalError

UsCr
Только в ней, но не в функциях описанных в ней?
и в функциях описанных в ней, они ведь тоже в ней находятся )

UsCr
У меня остался ещё вопрос: как в данном случае обойтись без global?
import random
rand = random.randint
randch = random.choice
arr = []

#generiruem massiv
def generate(KolSymb):

KolDvoetoch = 0 # !!!

def HowMuch():
j = rand(0,100)
if j%2==0: KolDvoetoch = 2
else: KolDvoetoch = 1

def GetDvoetoch():
if KolDvoetoch>0:
KolDvoetoch = KolDvoetoch-1
k = ":"
else: k = randch("abcdefghigklmnopqrstuvwxyz")


k = ""
HowMuch()

for i in range(KolSymb+1):
j = rand(0,10)
if j==0: k = randch("abcdefghigklmnopqrstuvwxyz")
else: GetDvoetoch()
arr.append(k)
print arr



Офлайн

#2 Ноя. 4, 2009 22:50:51

UsCr
От:
Зарегистрирован: 2009-11-04
Сообщения: 216
Репутация: +  0  -
Профиль   Отправить e-mail  

UnboundLocalError

pasaranax
import random
rand = random.randint
randch = random.choice
arr = []

#generiruem massiv
def generate(KolSymb):

KolDvoetoch = 0 # !!!

def HowMuch():
j = rand(0,100)
if j%2==0: KolDvoetoch = 2
else: KolDvoetoch = 1

def GetDvoetoch():
if KolDvoetoch>0:
KolDvoetoch = KolDvoetoch-1
k = ":"
else: k = randch("abcdefghigklmnopqrstuvwxyz")


k = ""
HowMuch()

for i in range(KolSymb+1):
j = rand(0,10)
if j==0: k = randch("abcdefghigklmnopqrstuvwxyz")
else: GetDvoetoch()
arr.append(k)
print arr
Третье сверху сообщение в теме. Я уже пробовал делать так. Не работает. Кстати, вообще код рабочий? Может у меня с софтом беда? Ставил IDLE из репозитоия. Под виндой аналогичная фигня выходит.



Офлайн

#3 Ноя. 5, 2009 00:28:50

pasaranax
От:
Зарегистрирован: 2009-06-13
Сообщения: 574
Репутация: +  0  -
Профиль   Отправить e-mail  

UnboundLocalError

Что-то я тоже запутался. Получается, питон не совсем очевидно себя ведет в этом случае. Он смотрит вперед выполняемой строки. Вот пример:

b = "hello"
def a():
print b
b = "world"
a()
Он вызывает такую же ошибку на строке ‘print b’, но если убрать следующую за ней строку ‘b = “world”’, то все в порядке. То есть в начале выполнения функции питон уже знает, что мы где-то в ней переопределили бывшую глобальную переменную своей локальной и не дает ее использовать до этого момента.
Кстати, изменить глобальную b внутри функции a он не даст, так что твой подход не будет работать, передавай во вложенные функции KolDvoetoch в качестве параметра, и не надо будет использовать global.



Отредактировано (Ноя. 5, 2009 00:32:59)

Офлайн

#4 Ноя. 5, 2009 01:48:41

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

UnboundLocalError

Нет. Все как раз очень очевидно.
Модули (а также классы и функции) - компилируются в байткод перед исполнением. Определение не совсем строгое - но сойдет.

>>> import dis
>>> b = "Hello"
>>> def a():
... print b
...
>>> dis.dis(a)
2 0 LOAD_GLOBAL 0 (b)
3 PRINT_ITEM
4 PRINT_NEWLINE
5 LOAD_CONST 0 (None)
8 RETURN_VALUE
Т.е. b в данном случае - глобальное имя, потому что не было присваивания (инициализации) внутри функции a.
То же самое с явным заданием global
>>> def a():
... global b
... print b
...
>>> dis.dis(a)
3 0 LOAD_GLOBAL 0 (b)
3 PRINT_ITEM
4 PRINT_NEWLINE
5 LOAD_CONST 0 (None)
8 RETURN_VALUE
А теперь - с инициализацией
>>> def a():
... print b
... b = 'world'
...
>>> dis.dis(a)
2 0 LOAD_FAST 0 (b)
3 PRINT_ITEM
4 PRINT_NEWLINE

3 5 LOAD_CONST 1 ('world')
8 STORE_FAST 0 (b)
11 LOAD_CONST 0 (None)
14 RETURN_VALUE
LOAD_FAST/STORE_FAST - опкоды для доступа к локальной переменной. Которой в начале еще нет.

С вложенными функциями - отдельная тема. Говоря коротко, питон смотрит в вызываемушую функцию перед тем, как смотреть в global scope. Если имя есть - оно помещается в func_closure и используется.
>>> def f():
... v = 'Hello'
... def g():
... print v
...
>>> dis.dis(f)
2 0 LOAD_CONST 1 ('Hello')
3 STORE_DEREF 0 (v)

3 6 LOAD_CLOSURE 0 (v)
9 BUILD_TUPLE 1
12 LOAD_CONST 2 (<code object g at 025802F0, file "<interactive input>", line 3>)
15 MAKE_CLOSURE 0
18 STORE_FAST 0 (g)
21 LOAD_CONST 0 (None)
24 RETURN_VALUE
>>>
Обратите внимание на LOAD_CLOSURE
В “классическом” Python 2.x нет способа переопределить имя для closure. Т.е. в g() нельзя написать v=3. Это будет распознано как создание локальной переменной. Стандартный способ обхода - использовать списки v = , затем v = ‘world’
В Python 3.x появилось новое слово nonlocal для этих целей.
>>> def f():
v = "Hello"
def g():
nonlocal v
print (v)
v = "world"
print (v)
return g

>>> dis.dis(f)
2 0 LOAD_CONST 1 ('Hello')
3 STORE_DEREF 0 (v)

3 6 LOAD_CLOSURE 0 (v)
9 BUILD_TUPLE 1
12 LOAD_CONST 2 (<code object g at 0x027BC698, file "<pyshell#14>", line 3>)
15 MAKE_CLOSURE 0
18 STORE_FAST 0 (g)

8 21 LOAD_FAST 0 (g)
24 RETURN_VALUE
>>> dis.dis(f())
5 0 LOAD_GLOBAL 0 (print)
3 LOAD_DEREF 0 (v)
6 CALL_FUNCTION 1
9 POP_TOP

6 10 LOAD_CONST 1 ('world')
13 STORE_DEREF 0 (v)

7 16 LOAD_GLOBAL 0 (print)
19 LOAD_DEREF 0 (v)
22 CALL_FUNCTION 1
25 POP_TOP
26 LOAD_CONST 0 (None)
29 RETURN_VALUE
Тема не совсем тривиальная - так что спрашивайте.



Офлайн

#5 Ноя. 5, 2009 09:37:38

UsCr
От:
Зарегистрирован: 2009-11-04
Сообщения: 216
Репутация: +  0  -
Профиль   Отправить e-mail  

UnboundLocalError

Так… А при передаче глобольной переменной в функцию в качестве параметра он даст её изменить? Она при этом не перестанет быть глобальной?



Офлайн

#6 Ноя. 5, 2009 10:27:36

UsCr
От:
Зарегистрирован: 2009-11-04
Сообщения: 216
Репутация: +  0  -
Профиль   Отправить e-mail  

UnboundLocalError

Вот оно:

import random
rand = random.randint
randch = random.choice
arr = []

def generate(KolSymb):
def proced():
def GetDvoetoch(KolDvoetoch):
if KolDvoetoch>0:
KolDvoetoch = KolDvoetoch-1
symb = ":"
else: symb = randch("abcdefghigklmnopqrstuvwxyz")
return symb
j = rand(0,100)
if j%2==0: KolDvoetoch = 2
else: KolDvoetoch = 1
j = rand(0,1)
if j==0: k = GetDvoetoch(KolDvoetoch)#KolDvoetoch)
else: k = randch("abcdefghigklmnopqrstuvwxyz")
return k

for i in range(KolSymb+1):
arr.append(proced())
print arr
Оно работает, но не так, как нужно. Сейчас выдаётся последовательность вида: , хотя должно быть не более двух двоеточий. Значит, опять не всё в порядке с KolDvoetoch(именно она контролирует количество двоеточий)



Офлайн

#7 Ноя. 5, 2009 10:32:13

Dimka665
От:
Зарегистрирован: 2008-09-19
Сообщения: 177
Репутация: +  0  -
Профиль   Отправить e-mail  

UnboundLocalError

import random
from UserString import MutableString

alphabet = "abcdefghigklmnopqrstuvwxyz"
m = MutableString(''.join(random.choice(alphabit) for i in xrange(random.randint(10,20))))
m += ';' * random.randint(1,2)
random.shuffle(m)



Отредактировано (Ноя. 5, 2009 10:34:03)

Офлайн

#8 Ноя. 5, 2009 10:41:13

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

UnboundLocalError

UsCr
Оно работает, но не так, как нужно.
Попробуйте решить задачу по частям:
1. Сгенерите список.
2. Вставьте двоеточия в случайные места.



Офлайн

#9 Ноя. 5, 2009 12:07:44

UsCr
От:
Зарегистрирован: 2009-11-04
Сообщения: 216
Репутация: +  0  -
Профиль   Отправить e-mail  

UnboundLocalError

Ох,да… Декомпозиция, мать наша…
Тема, я думаю закрыта. Остальное уже выходит за рамки.
Благодарю за помощь.



Офлайн

#10 Ноя. 5, 2009 12:22:46

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

UnboundLocalError

UsCr
Ох,да… Декомпозиция, мать наша…
Тема, я думаю закрыта. Остальное уже выходит за рамки.
Интересно было бы увидеть ваше решение.



Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version