Тот же цикл генерирует разные результаты [duplicate]

Исключение нулевого указателя - это индикатор того, что вы используете объект, не инициализируя его.

Например, ниже - класс ученика, который будет использовать его в нашем коде.

public class Student {

    private int id;

    public int getId() {
        return this.id;
    }

    public setId(int newId) {
        this.id = newId;
    }
}

Приведенный ниже код дает вам исключение с нулевым указателем.

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}

Поскольку вы используете Obj_Student, но вы забыли инициализировать его, как в правильном коде, показанном ниже:

public class School {

    Student obj_Student;

    public School() {
        try {
            obj_Student = new Student();
            obj_Student.setId(12);
            obj_Student.getId();
        }
        catch(Exception e) {
            System.out.println("Null Pointer ");
        }
    }
}
26
задан JSchwartz 16 August 2014 в 04:42
поделиться

3 ответа

Это потому, что data - итератор, вы можете использовать итератор только один раз. Например:

lst = [1, 2, 3]
it = iter(lst)

next(it)
=> 1
next(it)
=> 2
next(it)
=> 3
next(it)
=> StopIteration

Если мы перемещаем некоторые данные с помощью цикла for, последний StopIteration приведет к его завершению в первый раз. Если мы снова попытаемся перебрать его , мы будем получать исключение StopIteration, потому что итератор уже был использован.

Теперь для второго вопроса: что делать, если нам do нужно переходить через итератор более одного раза? Простым решением было бы создать список с элементами, и мы можем проходить его столько раз, сколько необходимо. Это все в порядке, если в списке несколько элементов:

data = list(db[3])

Но если есть много элементов, лучше создать независимые итераторы, используя tee() :

import itertools
it1, it2 = itertools.tee(db[3], n=2) # create as many as needed

Теперь мы можем поочередно перебирать по очереди:

for e in it1:
    print("doing this one time")

for e in it2:
    print("doing this two times")
25
ответ дан Óscar López 19 August 2018 в 04:11
поделиться
  • 1
    it.next() подходит для этого примера, поскольку вы можете себе представить, что метод next каким-то образом изменяет it, чтобы отслеживать то, что было получено (конечно, с большим количеством объектов, это «отслеживание» или вычисление из следующего значения возвращается в C-коде). Однако, как правило, при написании кода лучше использовать next(it), если вам не нужно поддерживать действительно старые версии python. Это передовая совместимость с python3.x, где it.next() переименован it.__next__() ... – mgilson 16 August 2014 в 04:52
  • 2
    @mgilson ok, получил это;) – Óscar López 16 August 2014 в 04:53
  • 3
    @JSchwartz попробуй это: data = list(db[3]). Теперь вы сможете пересекать data столько раз, сколько необходимо, потому что мы создали список с ним. – Óscar López 16 August 2014 в 04:57
  • 4
    Обратите внимание, что также возможно использовать itertools.tee для дублирования итератора;) – Ant 16 August 2014 в 09:50
  • 5
    @ ÓscarLópez Примечание к документации по tee: «Этот itertool может потребовать значительного вспомогательного хранилища (в зависимости от того, сколько временных данных необходимо сохранить). В общем случае, если один итератор использует большинство или все данные перед запуском другого итератора, быстрее использовать список () вместо tee (). & Quot; Поэтому, если вы используете it1 и it2, как вы в этом примере, вы вряд ли получите какую-либо реальную выгоду из tee (хотя, возможно, некоторые дополнительные накладные расходы). – svk 16 August 2014 в 20:39

Как только итератор исчерпан, он больше ничего не даст.

>>> it = iter([3, 1, 2])
>>> for x in it: print(x)
...
3
1
2
>>> for x in it: print(x)
...
>>>
9
ответ дан falsetru 19 August 2018 в 04:11
поделиться
  • 1
    это имеет смысл, но как мне обойти это? – JSchwartz 16 August 2014 в 04:55
  • 2
    @JSchwartz, конвертировать итератор в объект последовательности (list, tuple). Затем выполните итерацию объекта последовательности. (Только если размер csv не огромен) – falsetru 16 August 2014 в 04:56
  • 3
    @JSchwartz, Кроме того, если вы можете получить доступ к основному файловому объекту и который доступен для поиска. вы можете изменить положение файла перед вторым циклом: csv_file_object.seek(0) – falsetru 16 August 2014 в 04:56

Я хочу выполнить ответ @ ÓscarLópez для тех, кто ищет решение в 2017 году и использует python 2.7 или 3.

Метод tee () теперь не принимает аргументов ключевых слов и ждет второго аргумента целое число, а не ключевое слово. Это правильный способ использования tee ():

import itertools
it1, it2 = itertools.tee(db[3], 2)
2
ответ дан n.shalnov 19 August 2018 в 04:11
поделиться
Другие вопросы по тегам:

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