В соответствии с жизненным циклом MediaPlayer
, который вы можете просмотреть в руководстве API Android , я думаю, что вы должны называть reset()
вместо stop()
, а после этого снова готовиться медиаплеер (используйте только один), чтобы воспроизвести звук с самого начала. Также учтите, что звук может закончиться. Поэтому я также рекомендую реализовать setOnCompletionListener()
, чтобы убедиться, что если вы попытаетесь снова воспроизвести звук, он не сработает.
Python обрабатывает переменные в функциях по-разному в зависимости от того, присваиваете ли вы им значения из функции или нет. Если функция содержит любые присваивания переменной, она обрабатывается по умолчанию как локальная переменная. Поэтому, когда вы раскомментируете строку, вы пытаетесь ссылаться на локальную переменную до того, как ей присвоено какое-либо значение.
Если вы хотите, чтобы переменная c
ссылалась на глобальный c
put
global c
в качестве первой строки функции.
Что касается python 3, теперь есть
nonlocal c
, который вы можете использовать для ссылки на ближайшая область действия приложения, имеющая переменную c
.
Взгляд на разборку может прояснить, что происходит:
>>> def f():
... print a
... print b
... a = 1
>>> import dis
>>> dis.dis(f)
2 0 LOAD_FAST 0 (a)
3 PRINT_ITEM
4 PRINT_NEWLINE
3 5 LOAD_GLOBAL 0 (b)
8 PRINT_ITEM
9 PRINT_NEWLINE
4 10 LOAD_CONST 1 (1)
13 STORE_FAST 0 (a)
16 LOAD_CONST 0 (None)
19 RETURN_VALUE
Как вы можете видеть, байт-код для доступа к a есть LOAD_FAST
, а для b, LOAD_GLOBAL
. Это связано с тем, что компилятор идентифицировал, что a назначается внутри функции, и классифицирует его как локальную переменную. Механизм доступа для местных жителей принципиально отличается для глобальных переменных - им статически присваивается смещение в таблице переменных фрейма, что означает, что поиск является быстрым индексом, а не более дорогим исканием dict, как для глобальных. Из-за этого Python считывает строку print a
как «получает значение локальной переменной« a », содержащееся в слоте 0, и печатает его», и когда он обнаруживает, что эта переменная все еще не инициализирована, возникает исключение.
c+=1
присваивает c
, python предполагает, что назначенные переменные являются локальными, но в этом случае он не был объявлен локально.
Либо используйте ключевые слова global
или nonlocal
.
nonlocal
работает только в python 3, поэтому, если вы используете python 2 и не хотите, чтобы ваша переменная была глобальной, вы можете использовать изменяемый объект:
my_variables = { # a mutable object
'c': 3
}
def test():
my_variables['c'] +=1
test()
Вот две ссылки, которые могут помочь
ссылка описывает ошибку UnboundLocalError. Ссылка 2 может помочь с повторной записью тестовой функции. На основе второй ссылки исходная проблема может быть переписана как:
>>> a, b, c = (1, 2, 3)
>>> print (a, b, c)
(1, 2, 3)
>>> def test (a, b, c):
... print (a)
... print (b)
... print (c)
... c += 1
... return a, b, c
...
>>> a, b, c = test (a, b, c)
1
2
3
>>> print (a, b ,c)
(1, 2, 4)
Лучший способ получить переменную класса напрямую связан с именем класса
class Employee:
counter=0
def __init__(self):
Employee.counter+=1
Интерпретатор Python будет читать функцию как полный блок. Я думаю об этом, читая его в два прохода, один раз, чтобы собрать его закрытие (локальные переменные), а затем снова превратить его в байтовый код.
Как я уверен, вы уже знали, что имя, используемое слева от '=', неявно является локальной переменной. Не раз я был пойман, изменив переменный доступ к + =, и это неожиданно другая переменная.
Я также хотел указать, что это действительно не имеет ничего общего с глобальной областью. Вы получаете то же поведение с вложенными функциями.
Это не прямой ответ на ваш вопрос, но он тесно связан, так как это еще одна причина, вызванная связью между расширенным назначением и областями функций.
В большинстве случаев вы склонны думать о расширенное присвоение (a += b
) как точно эквивалентное простому присваиванию (a = a + b
). С этим можно столкнуться, хотя в одном случае. Позвольте мне объяснить:
Путем простого задания Python означает, что если a
передается в функцию (например, func(a)
, обратите внимание, что Python всегда передается по ссылке), тогда a = a + b
не будет изменять переданный a
. Вместо этого он просто изменит локальный указатель на a
.
Но если вы используете a += b
, то он иногда реализуется как:
a = a + b
или иногда (если существует метод) как:
a.__iadd__(b)
В первом случае (до тех пор, пока a
не объявляется глобальным), побочные эффекты отсутствуют за пределами локальной области, так как присвоение a
является просто обновлением указателя.
In второй случай, a
фактически изменит сам себя, поэтому все ссылки на a
будут указывать на модифицированную версию. Это демонстрируется следующим кодом:
def copy_on_write(a):
a = a + a
def inplace_add(a):
a += a
a = [1]
copy_on_write(a)
print a # [1]
inplace_add(a)
print a # [1, 1]
b = 1
copy_on_write(b)
print b # [1]
inplace_add(b)
print b # 1
Итак, трюк заключается в том, чтобы избежать расширенного назначения аргументов функции (я пытаюсь использовать его только для переменных локального / циклического). Используйте простое назначение, и вы будете в безопасности от неоднозначного поведения.
dict
, она внутренне только массив (locals()
заполняет dict
для возврата, но изменения в нем не создают новые locals
). Фаза разбора находит каждое присваивание локальному и преобразует из имени в позицию в этом массиве и использует эту позицию всякий раз, когда имя ссылается. При входе в функцию локаторы без аргументов инициализируются в placeholder, а UnboundLocalError
происходят, когда переменная читается, а связанный с ней индекс по-прежнему имеет значение-заполнитель.
– ShadowRanger
25 March 2016 в 20:49
В Python переменная, объявленная вне функции или в глобальной области действия, называется глобальной. Это означает, что глобальная переменная может быть доступна внутри или вне функции.
Но мы можем получить доступ только к глобальной переменной, но не можем ее модифицировать внутри функции. Если мы попытаемся сделать это, ошибка покажет
UnboundLocalError: локальная переменная 'c', на которую ссылаются перед присваиванием
blockquote>. Решение для этого - использовать глобальную ключевое слово.
a, b, c = (1, 2, 3) print(a, b, c) def test(): print(a) print(b) print(c) global c # (A) c+=1 # (B) test()
Если вы используете python 3, вы также можете использовать нелокальное ключевое слово
def test(): print(a) print(b) print(c) ninlocal c # (A) c+=1 # (B) test()
Лучший пример, который дает понять, это:
bar = 42
def foo():
print bar
if False:
bar = 0
при вызове foo()
, это также повышает UnboundLocalError
, хотя мы никогда не достигнем строки bar=0
, поэтому логически локальная переменная должна никогда не создаётся.
Тайна кроется в «Python - это интерпретируемый язык», и объявление функции foo
интерпретируется как единый оператор (т. е. составной оператор), он просто интерпретирует его тупо и создает локальные и глобальные области. Таким образом, bar
распознается в локальной области перед исполнением.
Для получения дополнительных примеров, таких как Читать это сообщение: http://blog.amir.rachum.com/blog/2013/07/09 / python-common-newbie-errors-part-2 /
В этом сообщении представлено полное описание и анализ области действия Python:
global
илиnonlocal
для принудительного глобального или нелокального назначения) – Steven 13 September 2011 в 13:00