简体   繁体   中英

Is there a way to lazy unpack an infinite generator?

In this situation, I want to define some IDs with increasing integer:

id_a, id_b, id_c = range(3)

That's OK for few IDs. But if there were many IDs, and will be more in future. It's too tedious to change the range(n) number for every time I add a new ID. So, I make an infinite generator for all new IDs:

def make_id():
    c_id = 0
    while True:
        yield c_id
        c_id += 1

Or, use the count straightly:

from itertools import count
make_id = count

Then, I wish I can define any number of IDs like this:

id_a, id_b, id_c, id_d, id_e = make_id()

But, it cause an error "ValueError: too many values to unpack"

BTW, it's OK in javascript:

let make_id = function *() {
    let c_id = 0;
    while(true) {
        yield c_id++;
    }
};

const [id_a, id_b, id_c, id_d, id_e] = make_id();

So, is there a way to lazy unpack an infinite generator in this situation in python?

===== Updated =====

In my project in javascript, I do something lie this:

const CFG_DBG = true;

let gen_sym = function *() {
    let cur = 0;
    while(true) {
        if(CFG_DBG) {
            yield 'private_attr_' + (cur++).toString();
        } else {
            yield Symbol();
        }
    }
};

let [
    PRIVATE_ATTR_A, PRIVATE_ATTR_B,
] = gen_sym();

let some_obj = {
    "public_attr_a": "this is public a",
    [PRIVATE_ATTR_A]: "you shouldn't read this",
};

let some_other_obj = {
    [PRIVATE_ATTR_B]: "you shouldn't read this too",
};

It can ensure the private attribute that can not be access in release version.

So, I want do something like this in python. I know the "__private_attr" name, but it can still be access with a prefix.

Python is, as a rule, much stricter about these sorts of things. You can do it only with an iterable with the exact size. If the iterable were finite, you could use:

a, b, c, *rest = iterable

But this will loop forever with an infinite iterable. And of course, it consumes the entire iterable, which is not what you want. One thing you can do is:

from itertools import islice, count

make_id = count()

id_a, id_b, id_c = islice(make_id, 3)

# do some stuff

id_d, id_e = islice(make_id, 2)

But you still have to be explicit about the size of the iterator.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM