1
00:00:05,380 --> 00:00:08,910
so I mentioned at the end of the previous
video that there was a useful

2
00:00:08,910 --> 00:00:14,290
application where recursive functions can come
in quite handy and that is dealing

3
00:00:14,290 --> 00:00:18,360
with files or specifically getting a
directory listing of a computer's file

4
00:00:18,360 --> 00:00:23,110
system now if you think about it modern
file systems are recursive in the sense

5
00:00:23,110 --> 00:00:26,960
that a directory can itself contained
other directories so once the

6
00:00:26,960 --> 00:00:31,190
functions listed all the objects in in
one directory you can call itself again

7
00:00:31,190 --> 00:00:35,220
for all the objects that are themselves
directories so you can see that's a

8
00:00:35,220 --> 00:00:41,700
really good use for a recursive function so what we are gonna do is
going to use the OS module to get the

9
00:00:41,700 --> 00:00:45,990
directory listing that's also useful for
checking if something is a directory so

10
00:00:45,990 --> 00:00:49,000
the function that we gonna write will
also have verified that the first directory

11
00:00:49,000 --> 00:00:53,580
passed to it does in fact exist before
attempts to do anything else it now before I

12
00:00:53,580 --> 00:00:57,570
go any further theirs another
example of recursion and that also

13
00:00:57,570 --> 00:01:02,490
provides an neat way to use a function
that's nested within another function if

14
00:01:02,490 --> 00:01:06,340
you really wanted to write a program to
visit all subdirectories then the OS

15
00:01:06,340 --> 00:01:10,630
module provides a walk function that
will do that for you and in fact I'll

16
00:01:10,630 --> 00:01:16,110
start off with that with the code we are about to write and I just want to bring up the documentation on the screen

17
00:01:16,110 --> 00:01:20,820
because like always its a good habit to
get into to check out documentation so

18
00:01:20,820 --> 00:01:27,910
bring it up on the screen paste it in my
browser you can see the link there we

19
00:01:27,910 --> 00:01:33,300
go so you can see some pretty useful information about the OS

20
00:01:33,300 --> 00:01:36,300
library that comes as part and parcel of Python

21
00:01:37,060 --> 00:01:44,700
and if we scroll down we should see the os.walk generate the file

22
00:01:44,700 --> 00:01:48,890
names in the directory tree by walking a
tree in a top-down or bottom-up so

23
00:01:48,890 --> 00:01:51,850
that's why we are gonna look at so again
when in doubt refer to the documentation

24
00:01:51,850 --> 00:01:56,640
its good way of learning more
information about any libraries that your

25
00:01:56,640 --> 00:02:06,000
about to use ok so let's go back and I'm gonna
create a new module and I'm going to I said module but I'm

26
00:02:06,000 --> 00:02:09,000
gonna create a new Python file I mean so....

27
00:02:11,110 --> 00:02:19,960
I'm gonna call this one filesanddirectories but it doesn't matter what you call it.....and lets start doing some coding so

28
00:02:19,960 --> 00:02:23,030
so firstly we are gonna import the os because we need to use that library...

29
00:02:26,000 --> 00:02:32,380
we're going to start with the os.walk so.....

30
00:02:32,380 --> 00:02:50,570
....

31
00:02:56,090 --> 00:03:01,910
.....

32
00:03:01,910 --> 00:03:08,160
....

33
00:03:08,160 --> 00:03:20,500
....so there's our
basic applications so the os.walk

34
00:03:20,500 --> 00:03:24,440
function as you can probably gather now
returns a list of tuples each tuple

35
00:03:24,440 --> 00:03:29,350
contains a directory name and also 2 lists
the first list the name

36
00:03:29,350 --> 00:03:33,520
is directories and you can see that
on line 6 because I'm referencing that and

37
00:03:33,520 --> 00:03:37,410
the second one its pretty obvious
on line 8 that we're dealing with the list of

38
00:03:37,410 --> 00:03:41,540
files was so there are the 2 list that also included in

39
00:03:41,540 --> 00:03:45,930
the tuple now if you have to work with the
file system the os module is worth reading up

40
00:03:45,930 --> 00:03:47,440
on and the

41
00:03:47,440 --> 00:03:50,680
reason is it contains a lot of useful
functions including this os.walk one

42
00:03:50,680 --> 00:03:55,370
so to see what walk is actually
doing we are going to create our own function

43
00:03:55,370 --> 00:03:58,710
and actually recurse through all
subdirectories and print out the contents

44
00:03:58,710 --> 00:04:03,370
but before we do that lets just run it
as it is now to see what it actually

45
00:04:03,370 --> 00:04:11,270
does so gonna do that.....and you can see on the right hand side the

46
00:04:11,270 --> 00:04:14,940
output has work so it's obviously
defaulted to the current folder and you

47
00:04:14,940 --> 00:04:19,240
can see we got a list of files and theirs
actually not really much in the way of

48
00:04:19,240 --> 00:04:21,579
directories their just to confirm that we
go back

49
00:04:21,579 --> 00:04:30,020
and have a look in here we click in reveal in finder and go into scope and namespaces and obviously this was the

50
00:04:30,020 --> 00:04:39,120
directory that it was dealing and hasn't really found much hidden files their starting with a dot on a MAC

51
00:04:39,120 --> 00:04:42,930
are hidden which is why we can't see those so let's continue on now

52
00:04:42,930 --> 00:04:47,930
and what we'll do is we'll create a
function now and put a bit more

53
00:04:47,930 --> 00:04:51,650
coding into it and will make a look
it a bit prettier by indenting the list as

54
00:04:51,650 --> 00:04:55,040
we enter a director etc so lets look at doing that

55
00:04:55,040 --> 00:05:00,840
so gonna come up here and will define a function so...

56
00:05:00,840 --> 00:05:03,840
....

57
00:05:06,290 --> 00:05:14,970
.....

58
00:05:15,780 --> 00:05:42,400
....

59
00:05:42,400 --> 00:05:57,550
.....we are going to write that shortly

60
00:05:57,550 --> 00:06:01,620
so in this particular function we are doing a
small amount of initialization the

61
00:06:01,620 --> 00:06:05,080
important bit is obviously making sure
that the starting directory that's

62
00:06:05,080 --> 00:06:09,860
passed to this function actually does
exist once that's done its gonna call a nested

63
00:06:09,860 --> 00:06:14,150
function that will recursively visit all
subdirectories and display its contents

64
00:06:14,150 --> 00:06:19,240
now the thing is the DIR_list function that we are about to

65
00:06:19,240 --> 00:06:23,890
call on line 8 is only actually
needed by this function so that's a good

66
00:06:23,890 --> 00:06:28,670
reason for defining it within list
directories so basically a function

67
00:06:28,670 --> 00:06:31,580
within a function so here is how we go about
doing that

68
00:06:31,580 --> 00:06:37,000
so we actually start in the list _directories function and we type.....

69
00:06:37,000 --> 00:06:49,520
.....

70
00:06:49,520 --> 00:06:56,500
...bearing in mind we already validated that the directory

71
00:06:56,500 --> 00:07:04,020
exists and we will by the time we call dir_list and will do a check their so put...

72
00:07:04,020 --> 00:07:07,740
....

73
00:07:07,740 --> 00:07:20,550
.....

74
00:07:20,550 --> 00:07:27,680
....so you can probably gather that one is

75
00:07:27,680 --> 00:07:30,930
doing that's actually putting together
the directory and the file and

76
00:07:30,930 --> 00:07:34,490
making a path for it so we are doing a
test here then to say whatever that was

77
00:07:34,490 --> 00:07:40,150
actually found is that directory
entry because an entry in a particular folder can be

78
00:07:40,150 --> 00:07:44,670
another folder or file so we are doing a check first

79
00:07:44,670 --> 00:07:48,960
to see whether it is a directory I'm
using the term folder but obviously directory

80
00:07:48,960 --> 00:07:55,420
and folder are terms interchangeable
terms they both mean the same thing so we are

81
00:07:55,420 --> 00:07:59,650
determine that it directory so....

82
00:07:59,650 --> 00:08:05,820
....

83
00:08:05,820 --> 00:08:17,740
...a hint with a tab its going to make
things look prettier and be able to indent correctly and

84
00:08:17,740 --> 00:08:24,230
in actual fact the next line......and

85
00:08:24,230 --> 00:08:29,820
we are getting an error their and we'll talk
about this shortly so...

86
00:08:29,820 --> 00:08:35,370
so using recursion we are calling back and using the
same function again and then we put....

87
00:08:35,370 --> 00:08:42,640
.....

88
00:08:43,179 --> 00:08:56,620
....

89
00:08:56,620 --> 00:09:02,310
....so that
should be our function so basically

90
00:09:02,310 --> 00:09:05,700
each time the inner function in a
function rather finds a directory

91
00:09:05,700 --> 00:09:11,750
it increases the tab stopped by 1 and calls itself to visit the new directory now when

92
00:09:11,750 --> 00:09:16,590
it returns it decreases the tab stops so you can see here on line 11 we're at

93
00:09:16,590 --> 00:09:20,660
increases the tab stop it calls the
function calls itself again and it

94
00:09:20,660 --> 00:09:26,480
decreases the tab again so it turns out to
be much simpler solution than trying to

95
00:09:26,480 --> 00:09:30,150
keep track of which directories which
already have been visited and shows

96
00:09:30,150 --> 00:09:34,470
how recursive functions can be very useful when
dealing with recursive structures such

97
00:09:34,470 --> 00:09:39,370
as the file system now of course that's all
it work of course so it's a good idea

98
00:09:39,370 --> 00:09:43,560
but IntelliJ as you can see on the screen
is actually showing errors and obviously

99
00:09:43,560 --> 00:09:46,260
the code isn't going to work at
the moment

100
00:09:46,260 --> 00:09:49,410
know if you're familiar with other
languages that allowed nested functions

101
00:09:49,410 --> 00:09:52,840
2 such languages are Algol and Pascal

102
00:09:52,840 --> 00:09:57,840
then you maybe a bit confused by the error so it's
saying that it can't resolve the

103
00:09:57,840 --> 00:10:01,830
references to tap stop but tab stop is clearly
defined in the outer scope as we can see

104
00:10:01,830 --> 00:10:06,530
on line 18 and in fact it looks
very similar to the situation we had

105
00:10:06,530 --> 00:10:10,720
with local variables shadowing those
with the same name in the outer scope

106
00:10:10,720 --> 00:10:15,150
and that's why IntelliJ was careful to refer them as variables in

107
00:10:15,150 --> 00:10:19,470
the outer scope rather than the global
variables so this is the same situation

108
00:10:19,470 --> 00:10:26,340
but the outer scope here is the function
list_directories of course that

109
00:10:26,340 --> 00:10:37,440
is defined on line 3 just need to make another line their to get rid of that error and the other thing we are gonna do down here now is

110
00:10:37,440 --> 00:10:43,810
to delete this code we don't need that anymore and we are going to be calling this when we figure

111
00:10:43,810 --> 00:10:46,900
out what's going on here with list_directories with the current folder

112
00:10:49,620 --> 00:10:57,140
so basically the errors that has coming up is
unresolved reference tab_stop as you can

113
00:10:57,140 --> 00:11:04,350
see their and that's what's actually causing the
problem now if we define a tab_stop on line

114
00:11:04,350 --> 00:11:10,810
within on line within the actual
function the inner function we can see what

115
00:11:10,810 --> 00:11:17,840
happens so lets try doing that so....when we do that we

116
00:11:17,840 --> 00:11:24,440
get the error that we've seen before shadows name
tab_stop from out of scope and the

117
00:11:24,440 --> 00:11:29,710
reason for that is now we've done that Python's created
a local variable called tab_stop

118
00:11:29,710 --> 00:11:34,270
just like it did when we
tried to assign it to a global variable in

119
00:11:34,270 --> 00:11:37,650
the blackjack program and as a result
its warning us that it's shadowing the

120
00:11:37,650 --> 00:11:42,500
variable in the outer scope which of course
is the variable on line 20 which is in the

121
00:11:42,500 --> 00:11:47,310
list_directors function so at this
point you might be wondering well maybe

122
00:11:47,310 --> 00:11:52,700
I need to use a global declaration on
line 7 to fix this lets try doing that

123
00:11:52,700 --> 00:12:01,100
....and you notice we got a different error here and will get rid of the equal 0...

124
00:12:05,250 --> 00:12:11,120
and if we try and run this now we actually get an error

125
00:12:11,120 --> 00:12:14,750
you can see the named error is named
tab_stop is not defined

126
00:12:14,750 --> 00:12:21,400
so clearly there's still something
going on here and the warning here is

127
00:12:21,400 --> 00:12:27,640
that remove redundant parenthesis and
so I'll just fix that up and that shouldn't

128
00:12:27,640 --> 00:12:33,150
have an extra bracket their so I am to use to
programming on other languages so lets fix that up

129
00:12:33,150 --> 00:12:36,950
at this point even though we know its
crash because I have shown you that if we

130
00:12:36,950 --> 00:12:42,160
run this again just to confirm its still crashing we are getting this variable error tab_stop is not

131
00:12:42,160 --> 00:12:45,930
defined and obviously there's now no errors
in the program but clearly theirs something

132
00:12:45,930 --> 00:12:51,280
still going on that is causing this
error so with Python 2 we would have been

133
00:12:51,280 --> 00:12:55,030
pretty much stuck here now their are ways to
get around this and of course we could

134
00:12:55,030 --> 00:12:58,520
just create a global variable but
Python 3 introduces another way to

135
00:12:58,520 --> 00:13:01,840
specify the scope of a variable in situations
like this

136
00:13:02,350 --> 00:13:06,650
and what we need to do is change the
global reference on line 7 to non-local

137
00:13:07,320 --> 00:13:14,010
if we do that we should find it works we type....and now if we run it

138
00:13:14,010 --> 00:13:19,130
you will find its now working correctly you can see the
directory listings working we are getting

139
00:13:19,130 --> 00:13:23,510
embedded file names and everything seems
to be working better than it did before

140
00:13:23,510 --> 00:13:27,560
so lets end the video here in the next video we're going to continue on we're

141
00:13:27,560 --> 00:13:31,870
going to just sort of talked about why this is
working and understanding the scope and

142
00:13:31,870 --> 00:13:35,760
how this non local keyword is helping
this to work so see you in the next

143
00:13:35,760 --> 00:13:35,970
video

