Попробуйте следующее:
public class <class> extends Activity{
private AlertDialog.Builder builder;
public void onCreate(Bundle savedInstanceState) {
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.<view>);
builder = new AlertDialog.Builder(<class>.this);
builder.setCancelable(true);
builder.setMessage(<message>);
builder.setInverseBackgroundForced(true);
//call the <className> class to execute
}
private class <className> extends AsyncTask<String, Void, String>{
protected String doInBackground(String... params) {
}
protected void onPostExecute(String result){
if(page.contains("error")) //when not subscribed
{
if(builder!=null){
builder.setNeutralButton("Ok",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton){
dialog.dismiss();
if(!<condition>)
{
try
{
String pl = "";
mHelper.<flow>(<class>.this, SKU, RC_REQUEST,
<listener>, pl);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
});
builder.show();
}
}
}
}
Примечание: это была ошибка в обработке CPython для
< / blockquote>yield
в выражениях выражений и выражений генератора, исправленных в Python 3.8, с предупреждением об отказе в Python 3.7. Смотрите отчет об ошибках Python и записи What's New для Python 3.7 и Python 3.8 .Выражения генератора, а также функции set и dict компилируются в объекты функции (генератора). В Python 3 переписные справки получают одинаковое обращение; все они, по существу, представляют собой новую вложенную область.
Вы можете увидеть это, если попытаетесь разобрать выражение генератора:
>>> dis.dis(compile("(i for i in range(3))", '', 'exec')) 1 0 LOAD_CONST 0 (<code object <genexpr> at 0x10f7530c0, file "", line 1>) 3 LOAD_CONST 1 ('<genexpr>') 6 MAKE_FUNCTION 0 9 LOAD_NAME 0 (range) 12 LOAD_CONST 2 (3) 15 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 18 GET_ITER 19 CALL_FUNCTION 1 (1 positional, 0 keyword pair) 22 POP_TOP 23 LOAD_CONST 3 (None) 26 RETURN_VALUE >>> dis.dis(compile("(i for i in range(3))", '', 'exec').co_consts[0]) 1 0 LOAD_FAST 0 (.0) >> 3 FOR_ITER 11 (to 17) 6 STORE_FAST 1 (i) 9 LOAD_FAST 1 (i) 12 YIELD_VALUE 13 POP_TOP 14 JUMP_ABSOLUTE 3 >> 17 LOAD_CONST 0 (None) 20 RETURN_VALUE
Вышеприведенное показывает, что выражение генератора скомпилированный в объект кода, загруженный как функция (
MAKE_FUNCTION
создает объект функции из объекта кода). Ссылка.co_consts[0]
позволяет нам видеть объект кода, сгенерированный для выражения, и используетYIELD_VALUE
так же, как функция генератора.Таким образом, выражение
yield
работает в этом контексте, поскольку компилятор рассматривает их как скрытые функции.Это ошибка;
yield
не имеет места в этих выражениях. Python грамматика до Python 3.7 позволяет (поэтому код компилируется), но спецификация выраженияyield
показывает, что использованиеyield
здесь не должно действительно работать :Выражение yield используется только при определении функции generator и, следовательно, может использоваться только в теле определения функции.
blockquote >Это было подтверждено как ошибка в выпуске 10544 . Разрешение ошибки заключается в том, что с помощью
yield
иyield from
будет поднятьSyntaxError
в Python 3.8 ; в Python 3.7 он вызываетDeprecationWarning
, чтобы гарантировать, что код перестает использовать эту конструкцию. Вы увидите то же предупреждение в Python 2.7.15 и выше, если вы используете переключатель командной строки-3
, включающий предупреждения о совместимости с Python 3.Появляется предупреждение 3.7.0b1 как это; включение предупреждений в ошибки дает вам исключение
SyntaxError
, как и в 3.8:>>> [(yield i) for i in range(3)] <stdin>:1: DeprecationWarning: 'yield' inside list comprehension <generator object <listcomp> at 0x1092ec7c8> >>> import warnings >>> warnings.simplefilter('error') >>> [(yield i) for i in range(3)] File "<stdin>", line 1 SyntaxError: 'yield' inside list comprehension
. Различия между тем, как
yield
в понимании списка иyield
в выражении генератора работают, вытекают из различия в том, как эти два выражения реализованы. В Python 3 в понимании списка используются вызовыLIST_APPEND
, чтобы добавить верхнюю часть стека в построенный список, в то время как выражение генератора вместо этого дает это значение. Добавление в(yield <expr>)
просто добавляет еще один код операцииYIELD_VALUE
:>>> dis.dis(compile("[(yield i) for i in range(3)]", '', 'exec').co_consts[0]) 1 0 BUILD_LIST 0 3 LOAD_FAST 0 (.0) >> 6 FOR_ITER 13 (to 22) 9 STORE_FAST 1 (i) 12 LOAD_FAST 1 (i) 15 YIELD_VALUE 16 LIST_APPEND 2 19 JUMP_ABSOLUTE 6 >> 22 RETURN_VALUE >>> dis.dis(compile("((yield i) for i in range(3))", '', 'exec').co_consts[0]) 1 0 LOAD_FAST 0 (.0) >> 3 FOR_ITER 12 (to 18) 6 STORE_FAST 1 (i) 9 LOAD_FAST 1 (i) 12 YIELD_VALUE 13 YIELD_VALUE 14 POP_TOP 15 JUMP_ABSOLUTE 3 >> 18 LOAD_CONST 0 (None) 21 RETURN_VALUE
Код операции
YIELD_VALUE
в индексах байт-кода 15 и 12 соответственно является дополнительным, кукушкой в гнезде. Таким образом, для генератора, использующего список, вы получаете 1 выход, каждый раз производя верхнюю часть стека (заменяя верхнюю часть стека на возвращаемое значениеyield
), а для варианта выражения генератора вы получаете верхнюю часть stack (целое число), а затем снова , но теперь стек содержит возвращаемое значениеyield
, и вы получитеNone
второй раз.Для списка тогда предполагается, что предполагаемый вывод объекта
list
все еще возвращен, но Python 3 рассматривает это как генератор, поэтому вместо этого значения возвратаStopIteration
в качестве атрибутаvalue
добавляется возвращаемое значение:>>> from itertools import islice >>> listgen = [(yield i) for i in range(3)] >>> list(islice(listgen, 3)) # avoid exhausting the generator [0, 1, 2] >>> try: ... next(listgen) ... except StopIteration as si: ... print(si.value) ... [None, None, None]
Те
None
объекты - это возвращаемые значения из выраженийyield
.И повторить это снова; эта же проблема относится к словарю и устанавливает понимание в Python 2 и Python 3; в Python 2 возвращаемые значения
yield
все еще добавляются к предполагаемому словарю или заданному объекту, а возвращаемое значение «дано» последнему вместо привязки к исключениюStopIteration
:>>> list({(yield k): (yield v) for k, v in {'foo': 'bar', 'spam': 'eggs'}.items()}) ['bar', 'foo', 'eggs', 'spam', {None: None}] >>> list({(yield i) for i in range(3)}) [0, 1, 2, set([None])]