Удивительное поведение области определения класса [дубликат]

ECMAScript 6 имеет «генераторы», которые позволяют вам легко программировать в асинхронном стиле.

function* myGenerator() {
    const callback = yield;
    let [response] = yield $.ajax("https://stackoverflow.com", {complete: callback});
    console.log("response is:", response);

    // examples of other things you can do
    yield setTimeout(callback, 1000);
    console.log("it delayed for 1000ms");
    while (response.statusText === "error") {
        [response] = yield* anotherGenerator();
    }
}

Для запуска вышеуказанного кода вы делаете это:

const gen = myGenerator(); // Create generator
gen.next(); // Start it
gen.next((...args) => gen.next([...args])); // Set its callback function

Если вам нужно настроить таргетинг на браузеры, которые не поддерживают ES6, вы можете запустить код через Babel или short-compiler для генерации ECMAScript 5.

Обратный вызов ...args завернут в массив и разрушен, когда вы их читаете так что шаблон может справиться с обратными вызовами, которые имеют несколько аргументов. Например, с узлом fs :

const [err, data] = yield fs.readFile(filePath, "utf-8", callback);

114
задан Martijn Pieters 29 March 2014 в 02:22
поделиться

3 ответа

152
ответ дан user2357112 31 August 2018 в 11:24
поделиться

Принятый ответ обеспечивает отличную информацию, но здесь, похоже, есть несколько других морщин - различия между пониманием списка и выражениями генератора. Демонстрация, с которой я играл:

class Foo:

    # A class-level variable.
    X = 10

    # I can use that variable to define another class-level variable.
    Y = sum((X, X))

    # Works in Python 2, but not 3.
    # In Python 3, list comprehensions were given their own scope.
    try:
        Z1 = sum([X for _ in range(3)])
    except NameError:
        Z1 = None

    # Fails in both.
    # Apparently, generator expressions (that's what the entire argument
    # to sum() is) did have their own scope even in Python 2.
    try:
        Z2 = sum(X for _ in range(3))
    except NameError:
        Z2 = None

    # Workaround: put the computation in lambda or def.
    compute_z3 = lambda val: sum(val for _ in range(3))

    # Then use that function.
    Z3 = compute_z3(X)

    # Also worth noting: here I can refer to XS in the for-part of the
    # generator expression (Z4 works), but I cannot refer to XS in the
    # inner-part of the generator expression (Z5 fails).
    XS = [15, 15, 15, 15]
    Z4 = sum(val for val in XS)
    try:
        Z5 = sum(XS[i] for i in range(len(XS)))
    except NameError:
        Z5 = None

print(Foo.Z1, Foo.Z2, Foo.Z3, Foo.Z4, Foo.Z5)
1
ответ дан FMc 31 August 2018 в 11:24
поделиться

В основном это проблема в Python 3. Я надеюсь, что они меняют ее.

Bugged (работает в версии 2.7):

x = 4
y = [x+i for i in range(1)]

Чтобы обойти это (работает в 3+) :

x = 4
y = (lambda x=x: [x+i for i in range(1)])()
6
ответ дан Jonathan 31 August 2018 в 11:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: