Attribute Error: next ()

I want to loop on the same level with next() with os.walk

The critical line of my code is:

 for root, dirs, files in os.walk(dir).next(1): 

Error:

AttributeError: object 'generator' does not have attribute 'next'

I tried using .next(x) to replace the old next()[1] as suggested by the community, but this also does not work.

+4
source share
1 answer

You are using python3. In python3, the next() method has been replaced by __next__ . This method allows you not to accept any arguments (i.e. a.__next__(1) is an error). They push the iterator one by one. To promote it across multiple items, call next several times.

If you want to use the iterator in one way, I would suggest using the built-in function next :

 >>> L = (x for x in range(10)) >>> next(L) 0 >>> next(L) 1 

Note: the next built-in function was added in python2.6, I suppose, therefore, it is safe to use even in python2.

However , in your code it makes no sense to call next . What are you trying to achieve with him?

Doing:

 for root, dirs, files in next(os.walk(dir)): 

An error will occur because next returns the first os.walk element, which is a three-element tuple, contains lists of strings. But the for loop will iterate over the tuple, trying to unpack one list into root, dirs, files . If any directory has more or less than 3 files / subdirectories, the code will fail.

If you want to skip only the first directory, you will have to name next separately:

 iterable = os.walk(directory) next(iterable) # throw away first iteration for root, dirs, files in iterable: #... 

If you want to iterate over directories only, as Martijn intended, then you don't need to do anything in particular. Just don't use the root and files variables in a loop. In this case, I would suggest renaming them to _ , which is often used to indicate a variable that we should assign, but not used at all:

 for _, dirs, _ in os.walk(directory): # Work only on "dirs". Don't care for "_"s 

If you want to use the first n elements of the iteration, you can use itertools.islice and collections.deque for fast and without memory usage:

 from itertools import islice from collections import deque def drop_n_elements(n, iterable): deque(islice(iterable, n), maxlen=0) 

And then use it like:

 iterable = os.walk(directory) drop_n_elements(N, iterable) # throw away first N iterations for root, dirs, files in iterable: # ... 

It occurred to me that there is an even faster and easier way to discard the first n elements of the iteration:

 def drop_n_elements(n, iterable): next(islice(iterable, n, n), None) 

It is slightly faster than using deque(..., maxlen=0) because it only makes one call to the next islice method.

+16
source

Source: https://habr.com/ru/post/1499919/


All Articles