I want to loop one level deep using next()
with os.walk
Critical line of my code:
for root, dirs, files in os.walk(dir).next(1):
Error:
AttributeError: 'generator' object has no attribute 'next'
I tried using .next(x)
to replace old next()[1]
as suggested by community, but this also doesnt work.
You are using python3. In python3 the next()
method was replaced by __next__
.
These method do not accept any argument(i.e. a.__next__(1)
is an error).
They advance the iterator by one. To advance it by more elements call next
repeatedly.
If you want to advance the iterator by one use, I'd suggest to use the next
built-in function:
>>> 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 believe, so it's safe to use even in python2.
However, in your code it does not make sense calling next
at all. What are you trying to achieve with it?
Doing:
for root, dirs, files in next(os.walk(dir)):
Will raise an error, since next
returns the first element of os.walk
, which is a three element tuple, containings lists of strings. But the for
loop will iterate over the tuple, trying to unpack a single 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'll have to call next
separately:
iterable = os.walk(directory)
next(iterable) # throw away first iteration
for root, dirs, files in iterable:
#...
If you wanted to iterate only on the directories, as speculated by Martijn, then you don't have to do anything in particular. Simply don't use the root
and files
variables in the loop. In this case I'd suggest to rename them to _
, which is often used to indicate a variable that we must assign, but isn't used at all:
for _, dirs, _ in os.walk(directory):
# Work only on "dirs". Don't care for "_"s
If you want to consume the first n
elements of an iterable, you can use itertools.islice
and collections.deque
to do it fast and without memory consumption:
from itertools import islice
from collections import deque
def drop_n_elements(n, iterable):
deque(islice(iterable, n), maxlen=0)
And then use it as:
iterable = os.walk(directory)
drop_n_elements(N, iterable) # throw away first N iterations
for root, dirs, files in iterable:
# ...
It just occurred to me that there is an even faster and easier way to drop the first n elements of an iterable:
def drop_n_elements(n, iterable):
next(islice(iterable, n, n), None)
It is slightly faster than using deque(..., maxlen=0)
because it does only a single call to the next
method of islice
.
for root, dirs, files in os.walk(dir).__next__()[1]:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With