WEBVTT

1
00:00:00.040 --> 00:00:02.600
<v Speaker 1>All right, buckle up everyone, because today we're taking a

2
00:00:02.640 --> 00:00:04.639
<v Speaker 1>deep dive into Python two oh one.

3
00:00:04.799 --> 00:00:07.559
<v Speaker 2>We're going way past Python one oh one here. Think

4
00:00:07.599 --> 00:00:09.279
<v Speaker 2>of this as your insider's.

5
00:00:08.720 --> 00:00:13.199
<v Speaker 1>Guide to some seriously powerful Python techniques. We've got excerpts

6
00:00:13.199 --> 00:00:16.280
<v Speaker 1>from the book, the table of contents, the chapter intros,

7
00:00:16.359 --> 00:00:19.320
<v Speaker 1>even some code snippets. By the time we're done, you'll

8
00:00:19.359 --> 00:00:22.120
<v Speaker 1>be writing Python code that I'll make your colleagues say, whoa,

9
00:00:22.519 --> 00:00:23.280
<v Speaker 1>how they do that.

10
00:00:23.600 --> 00:00:26.320
<v Speaker 2>Python two one is broken down into four parts. We've

11
00:00:26.359 --> 00:00:29.760
<v Speaker 2>got intermediate modules, odds and ends, Web and testing.

12
00:00:30.519 --> 00:00:34.399
<v Speaker 1>Hmmm, that odds and ends section sounds intriguing. What's in there?

13
00:00:34.679 --> 00:00:38.560
<v Speaker 2>That's where we're focusing today. Covers unicode generators and iterators

14
00:00:38.560 --> 00:00:39.399
<v Speaker 2>and benchmarking.

15
00:00:39.439 --> 00:00:41.600
<v Speaker 1>All right, let's jump right in. I know Python two

16
00:00:41.640 --> 00:00:44.280
<v Speaker 1>oh one has a whole section on modules, and I'm

17
00:00:44.320 --> 00:00:46.840
<v Speaker 1>really curious about ar parse. I've heard it can be

18
00:00:46.880 --> 00:00:49.039
<v Speaker 1>a game changer for building command line tools.

19
00:00:49.119 --> 00:00:51.439
<v Speaker 2>Yeah. Arc parse is awesome for that. It makes handling

20
00:00:51.479 --> 00:00:54.799
<v Speaker 2>command line arguments so much easier, especially if you're dealing

21
00:00:54.840 --> 00:00:56.600
<v Speaker 2>with things like usernames and passwords.

22
00:00:56.679 --> 00:00:58.520
<v Speaker 1>Uh huh, sensitive data makes sense.

23
00:00:58.679 --> 00:01:00.960
<v Speaker 2>The book has a really good example on page sixteen,

24
00:01:01.479 --> 00:01:06.519
<v Speaker 2>where they walk you through defining arguments setting defaults. They

25
00:01:06.560 --> 00:01:09.400
<v Speaker 2>even use chain map to manage those defaults in a

26
00:01:09.400 --> 00:01:10.239
<v Speaker 2>really smart way.

27
00:01:10.480 --> 00:01:12.480
<v Speaker 1>I've heard of chain map but never really used it.

28
00:01:12.519 --> 00:01:13.719
<v Speaker 1>What's so special about it?

29
00:01:13.840 --> 00:01:16.120
<v Speaker 2>Well, instead of having a bunch of IFL statements to

30
00:01:16.120 --> 00:01:19.480
<v Speaker 2>handle defaults, you've used chain map to kind of layer

31
00:01:19.560 --> 00:01:21.560
<v Speaker 2>your defaults and control where they come from.

32
00:01:22.000 --> 00:01:23.920
<v Speaker 1>Oh. That sounds a lot cleaner than the way I've

33
00:01:23.959 --> 00:01:26.879
<v Speaker 1>been doing it. The example also highlights some specific lines

34
00:01:26.879 --> 00:01:29.200
<v Speaker 1>of code. You've got line four marked right.

35
00:01:29.239 --> 00:01:31.840
<v Speaker 2>Line four is where they import chain map from the

36
00:01:31.879 --> 00:01:32.719
<v Speaker 2>collections module.

37
00:01:32.879 --> 00:01:36.200
<v Speaker 1>Ah. Collections, Now that's a module I have used and

38
00:01:36.319 --> 00:01:38.319
<v Speaker 1>loved so many useful tools in there.

39
00:01:38.359 --> 00:01:40.879
<v Speaker 2>It's a gold mine for sure. And they use chain

40
00:01:40.920 --> 00:01:43.640
<v Speaker 2>map in this example to really streamline how the defaults

41
00:01:43.640 --> 00:01:44.200
<v Speaker 2>are handled.

42
00:01:44.280 --> 00:01:46.519
<v Speaker 1>I'm seeing how all these pieces fit together. Now, I

43
00:01:46.560 --> 00:01:49.319
<v Speaker 1>see you've also got lines fourteen and fifteen highlighted.

44
00:01:49.680 --> 00:01:52.680
<v Speaker 2>Those lines are key to They use a dictionary comprehension

45
00:01:53.000 --> 00:01:56.920
<v Speaker 2>and the VIRS function. It's a really slick way to

46
00:01:57.000 --> 00:01:59.599
<v Speaker 2>grab the arguments that the users actually provided.

47
00:02:00.000 --> 00:02:03.120
<v Speaker 1>So basically, arc parse is like the velvet rope for

48
00:02:03.200 --> 00:02:06.319
<v Speaker 1>your command line tools. Letting the right data in and

49
00:02:06.400 --> 00:02:07.560
<v Speaker 1>keeping the riff raff out.

50
00:02:07.760 --> 00:02:10.599
<v Speaker 2>Uh huh, yeah, I like that analogy. Okay, So moving

51
00:02:10.639 --> 00:02:13.120
<v Speaker 2>on from arc pars, we've got collections on the docket.

52
00:02:13.240 --> 00:02:15.800
<v Speaker 1>Yes, I've got to sing the praises of counter. It's

53
00:02:15.800 --> 00:02:20.479
<v Speaker 1>made counting occurrences in like text files so incredibly easy.

54
00:02:20.560 --> 00:02:23.280
<v Speaker 2>Oh. Counter is a life saver. But it's more than

55
00:02:23.319 --> 00:02:26.879
<v Speaker 2>just counting. It's got all these helpful methods like most common,

56
00:02:27.120 --> 00:02:29.919
<v Speaker 2>which can be super handy for things like figuring out

57
00:02:29.960 --> 00:02:32.080
<v Speaker 2>the most frequent words in a document right.

58
00:02:31.960 --> 00:02:34.840
<v Speaker 1>And it handles all the tedious counting logic behind the scenes,

59
00:02:35.199 --> 00:02:37.240
<v Speaker 1>so your code stays clean and readable.

60
00:02:37.479 --> 00:02:39.960
<v Speaker 2>Speaking of clean code, have you ever run into those

61
00:02:40.120 --> 00:02:42.759
<v Speaker 2>pesky kier exceptions when working with dictionaries?

62
00:02:42.840 --> 00:02:44.599
<v Speaker 1>Oh? Yeah, all the time. It's like they sneak up

63
00:02:44.639 --> 00:02:45.919
<v Speaker 1>on you when you least expect it.

64
00:02:46.080 --> 00:02:48.919
<v Speaker 2>Well, default dickt is your new best friend. It lets

65
00:02:48.919 --> 00:02:51.120
<v Speaker 2>you set a default value for any key that doesn't

66
00:02:51.120 --> 00:02:52.439
<v Speaker 2>already exist in the dictionary.

67
00:02:52.879 --> 00:02:56.000
<v Speaker 1>Ah. So instead of crashing with a keyr, it just

68
00:02:56.159 --> 00:02:59.080
<v Speaker 1>gracefully provides a default value exactly.

69
00:02:59.360 --> 00:03:02.120
<v Speaker 2>The example page fourteen really shows how elegant it can be.

70
00:03:02.360 --> 00:03:05.000
<v Speaker 2>Lines one, two, and four especially.

71
00:03:04.680 --> 00:03:07.280
<v Speaker 1>Okay, I'm definitely bookmarking that example for later. Now. DK

72
00:03:07.400 --> 00:03:09.759
<v Speaker 1>is one I haven't used much. What's the skip on that?

73
00:03:10.159 --> 00:03:13.960
<v Speaker 2>Think of DKE as a list that's optimized for adding

74
00:03:13.960 --> 00:03:16.120
<v Speaker 2>and removing elements from both ends, so.

75
00:03:16.199 --> 00:03:18.719
<v Speaker 1>Like a queue, but you can add things to the

76
00:03:18.719 --> 00:03:19.479
<v Speaker 1>front or the back.

77
00:03:19.639 --> 00:03:23.039
<v Speaker 2>Yeah, it's really efficient if you need to process data

78
00:03:23.719 --> 00:03:26.479
<v Speaker 2>in a specific order, like first in, first out or

79
00:03:26.560 --> 00:03:27.639
<v Speaker 2>last in first out.

80
00:03:27.719 --> 00:03:30.159
<v Speaker 1>Gotcha. Page nineteen has an example of a deck that's

81
00:03:30.280 --> 00:03:33.639
<v Speaker 1>created from the lowercase letters right lines one, two, and three.

82
00:03:33.719 --> 00:03:36.560
<v Speaker 2>I think those lines set up the deck. The cool

83
00:03:36.560 --> 00:03:38.479
<v Speaker 2>part is that it has meteds like a pen left

84
00:03:38.520 --> 00:03:41.039
<v Speaker 2>and pop left, so you have a lot of control

85
00:03:41.159 --> 00:03:42.479
<v Speaker 2>over where things go in the deck.

86
00:03:42.879 --> 00:03:45.159
<v Speaker 1>Okay, I'm starting to see how deep could be useful

87
00:03:45.159 --> 00:03:48.639
<v Speaker 1>in some specific situations. What about named tupole. I haven't

88
00:03:48.680 --> 00:03:49.759
<v Speaker 1>used that one much either.

89
00:03:49.879 --> 00:03:53.479
<v Speaker 2>If you like clean and readable code, you'll love named tuple.

90
00:03:53.560 --> 00:03:56.360
<v Speaker 2>It's basically a tuple, but you can access elements by

91
00:03:56.439 --> 00:03:58.520
<v Speaker 2>name instead of just their position, so it's.

92
00:03:58.400 --> 00:04:01.840
<v Speaker 1>Like a regular tuople, but with more meaningful labels.

93
00:04:01.919 --> 00:04:04.840
<v Speaker 2>Exactly. It makes your code so much easier to understand,

94
00:04:05.000 --> 00:04:08.240
<v Speaker 2>especially when you're dealing with data that has multiple fields.

95
00:04:08.639 --> 00:04:12.199
<v Speaker 1>The book uses that autoparts example again on page twenty.

96
00:04:12.319 --> 00:04:14.479
<v Speaker 1>You've marked lines one, three, five, and six.

97
00:04:14.680 --> 00:04:17.959
<v Speaker 2>Yeah, that's going. They define a name tuple called parts

98
00:04:18.279 --> 00:04:20.879
<v Speaker 2>with feels like make, model, and year.

99
00:04:21.600 --> 00:04:24.160
<v Speaker 1>So instead of remembering that, say the year is at

100
00:04:24.199 --> 00:04:26.439
<v Speaker 1>index two, you can just access it as parts dot

101
00:04:26.560 --> 00:04:27.439
<v Speaker 1>year exactly.

102
00:04:27.480 --> 00:04:29.120
<v Speaker 2>It makes the code so much more intuitive.

103
00:04:29.240 --> 00:04:32.879
<v Speaker 1>Okay, last one for collections order dict. This is for

104
00:04:32.920 --> 00:04:36.079
<v Speaker 1>when the order you add things to a dictionary actually matters.

105
00:04:35.839 --> 00:04:38.480
<v Speaker 2>Right, you got it. A regular dictionary doesn't care about

106
00:04:38.519 --> 00:04:41.959
<v Speaker 2>the order of its keys, but sometimes that order is crucial.

107
00:04:42.439 --> 00:04:45.600
<v Speaker 2>Think configuration files or anything where the sequence matters.

108
00:04:45.879 --> 00:04:48.160
<v Speaker 1>Yeah, that makes sense. So we've covered our parts and

109
00:04:48.240 --> 00:04:51.040
<v Speaker 1>taken a tour of collections. What's next on the module menu.

110
00:04:51.199 --> 00:04:54.240
<v Speaker 2>Context slib is up next. It's all about context managers

111
00:04:54.240 --> 00:04:57.720
<v Speaker 2>and resource handling. Think of the with statement in Python.

112
00:04:57.879 --> 00:05:00.879
<v Speaker 1>Ah, yes, the with statement. It's like a safety net

113
00:05:00.879 --> 00:05:03.680
<v Speaker 1>for making sure resources get closed properly exactly.

114
00:05:04.079 --> 00:05:07.000
<v Speaker 2>But contextlib takes it a step further and gives you

115
00:05:07.079 --> 00:05:11.240
<v Speaker 2>tools like suppress, which can silently ignore certain types of exceptions.

116
00:05:11.439 --> 00:05:14.839
<v Speaker 1>So instead of a big try accept block, you can

117
00:05:14.959 --> 00:05:21.360
<v Speaker 1>just use suppress to handle expected exceptions without.

118
00:05:22.879 --> 00:05:24.839
<v Speaker 2>Elevent and easier to be love it.

119
00:05:24.879 --> 00:05:27.879
<v Speaker 1>Okay, speaking of elegant code, what about funk Tools. I'm

120
00:05:27.879 --> 00:05:28.759
<v Speaker 1>intrigued by the name.

121
00:05:29.040 --> 00:05:31.480
<v Speaker 2>Funk Tools is all about taking your functions to the

122
00:05:31.519 --> 00:05:35.160
<v Speaker 2>next level. It's got tools for things like caching, partial,

123
00:05:35.199 --> 00:05:38.000
<v Speaker 2>function application, and even function overloading.

124
00:05:38.120 --> 00:05:39.639
<v Speaker 1>Whoa lots of goodies in there.

125
00:05:39.680 --> 00:05:42.759
<v Speaker 2>For example, there's l rucash, which is a decorator that

126
00:05:42.839 --> 00:05:44.639
<v Speaker 2>catches the results of your function calls.

127
00:05:44.800 --> 00:05:46.959
<v Speaker 1>So if I have a function that does some heavy computation,

128
00:05:47.160 --> 00:05:49.360
<v Speaker 1>all roucash can store the results, so the next time

129
00:05:49.360 --> 00:05:51.199
<v Speaker 1>I call it with the same inputs, it doesn't have

130
00:05:51.240 --> 00:05:52.920
<v Speaker 1>to do all that work again exactly.

131
00:05:52.959 --> 00:05:55.959
<v Speaker 2>It's a brilliant way to boost performance. Page thirty one

132
00:05:56.000 --> 00:05:58.000
<v Speaker 2>has an example where they use it to speed up

133
00:05:58.000 --> 00:05:59.000
<v Speaker 2>fetching web pages.

134
00:05:59.160 --> 00:06:01.800
<v Speaker 1>Ah. So it's perfect for those functions that get called

135
00:06:01.839 --> 00:06:03.600
<v Speaker 1>repeatedly with the same arguments.

136
00:06:03.720 --> 00:06:06.519
<v Speaker 2>Yep. And then there's partial, which is all about creating

137
00:06:06.560 --> 00:06:09.879
<v Speaker 2>specialized versions of your functions with some of the arguments

138
00:06:09.920 --> 00:06:10.639
<v Speaker 2>pre set.

139
00:06:11.000 --> 00:06:13.040
<v Speaker 1>So it's like a function template where some of the

140
00:06:13.079 --> 00:06:14.199
<v Speaker 1>blanks are already filled in.

141
00:06:14.319 --> 00:06:17.639
<v Speaker 2>You got it. The example on page thirty two uses

142
00:06:17.680 --> 00:06:19.800
<v Speaker 2>a simple ad function to show how it works.

143
00:06:20.120 --> 00:06:23.240
<v Speaker 1>Let me guess they use partial to create a version

144
00:06:23.279 --> 00:06:26.040
<v Speaker 1>of AD where one of the numbers is already fixed.

145
00:06:26.240 --> 00:06:29.240
<v Speaker 2>Spot on, they create a version of AD that always

146
00:06:29.240 --> 00:06:31.800
<v Speaker 2>adds two to whatever number you give it. It's a

147
00:06:31.839 --> 00:06:32.360
<v Speaker 2>knee trick.

148
00:06:32.600 --> 00:06:35.399
<v Speaker 1>Okay, I'm starting to see how partial could come in handy,

149
00:06:35.959 --> 00:06:39.600
<v Speaker 1>especially for things like callbacks or event handlers.

150
00:06:39.759 --> 00:06:42.879
<v Speaker 2>Now for something really powerful, we've got single dispatch.

151
00:06:42.959 --> 00:06:46.560
<v Speaker 1>Single dispatch that rings a bell. Isn't that for function overloading?

152
00:06:46.920 --> 00:06:49.879
<v Speaker 2>You know your stuff. It lets you define multiple versions

153
00:06:49.920 --> 00:06:53.079
<v Speaker 2>of the same function that handle different input types differently.

154
00:06:53.399 --> 00:06:55.199
<v Speaker 1>So I could have one AD function that works for

155
00:06:55.279 --> 00:06:58.319
<v Speaker 1>numbers and another one that works for strings, and single

156
00:06:58.360 --> 00:07:00.519
<v Speaker 1>dispatch figures out which one to use based on the

157
00:07:00.519 --> 00:07:01.240
<v Speaker 1>input type.

158
00:07:01.360 --> 00:07:04.079
<v Speaker 2>Yeah, it's a really elegant way to handle those situations

159
00:07:04.079 --> 00:07:06.920
<v Speaker 2>where you want the same function to behave differently depending

160
00:07:06.920 --> 00:07:08.240
<v Speaker 2>on the type of data it's given.

161
00:07:08.360 --> 00:07:11.199
<v Speaker 1>The code on page thirty five shows how to overload

162
00:07:11.199 --> 00:07:13.879
<v Speaker 1>the AD function for injurers, strings, and lists.

163
00:07:14.319 --> 00:07:17.959
<v Speaker 2>Right, each version of AD has its own specific logic

164
00:07:18.040 --> 00:07:21.759
<v Speaker 2>for handling those types. Lines ten, sixteen, and twenty two

165
00:07:21.879 --> 00:07:23.560
<v Speaker 2>show those different implementations.

166
00:07:24.120 --> 00:07:27.279
<v Speaker 1>This is making me rethink how I approach function design.

167
00:07:27.360 --> 00:07:32.519
<v Speaker 1>And Python. Okay, last stop on our module tour. Importlib, ah,

168
00:07:32.639 --> 00:07:35.079
<v Speaker 1>import lib. It's like the control panel for your imports

169
00:07:35.079 --> 00:07:37.360
<v Speaker 1>in Python. You can do all sorts of fancy things

170
00:07:37.360 --> 00:07:37.680
<v Speaker 1>with it.

171
00:07:37.839 --> 00:07:39.199
<v Speaker 2>Fancy in a good way, I hope.

172
00:07:39.240 --> 00:07:42.680
<v Speaker 1>Definitely. You can do dynamic imports where you only load

173
00:07:42.680 --> 00:07:44.800
<v Speaker 1>a module when you actually need it. You can also

174
00:07:44.839 --> 00:07:47.120
<v Speaker 1>do safety checks to make sure a module exists before

175
00:07:47.160 --> 00:07:48.040
<v Speaker 1>you try to import it.

176
00:07:48.120 --> 00:07:51.759
<v Speaker 2>That sounds incredibly useful for preventing those module not found errors.

177
00:07:52.319 --> 00:07:54.600
<v Speaker 1>And it can even let you import modules directly from

178
00:07:54.639 --> 00:07:56.759
<v Speaker 1>source files, which can be handy in some cases.

179
00:07:56.839 --> 00:07:59.040
<v Speaker 2>Page fifty one shows how to check if a module

180
00:07:59.079 --> 00:08:02.439
<v Speaker 2>exists using import lb right. Lines three, nine, twelve, and

181
00:08:02.519 --> 00:08:03.720
<v Speaker 2>fourteen are the key ones.

182
00:08:03.879 --> 00:08:07.439
<v Speaker 1>Those lines demonstrate how to gracefully handle the situation where

183
00:08:07.439 --> 00:08:09.519
<v Speaker 1>a module might not be available.

184
00:08:09.319 --> 00:08:11.600
<v Speaker 2>So instead of crashing, your code can check if the

185
00:08:11.639 --> 00:08:13.639
<v Speaker 2>module exists and then take appropriate action.

186
00:08:13.839 --> 00:08:15.959
<v Speaker 1>That's the goal. It's all about writing a robust and

187
00:08:16.040 --> 00:08:18.920
<v Speaker 1>reliable Python code. Okay, Before we move on, I want

188
00:08:18.920 --> 00:08:21.160
<v Speaker 1>to circle back to a couple of concepts that I'm

189
00:08:21.199 --> 00:08:24.319
<v Speaker 1>still a bit fuzzy on. Iterators and generators.

190
00:08:24.399 --> 00:08:26.839
<v Speaker 2>All right, good ones. They can be a little tricky

191
00:08:26.839 --> 00:08:30.720
<v Speaker 2>to wrap your head around it. First, let's start with iterables. Basically,

192
00:08:30.759 --> 00:08:33.759
<v Speaker 2>anything you can loop over in Python is an iterable,

193
00:08:34.039 --> 00:08:35.039
<v Speaker 2>like a list or a tupple.

194
00:08:35.279 --> 00:08:39.559
<v Speaker 1>Right, I get that. So where do iterators fit in Well.

195
00:08:39.320 --> 00:08:42.360
<v Speaker 2>An iterator is what actually makes the looping possible. It's

196
00:08:42.360 --> 00:08:44.919
<v Speaker 2>like a little machine that keeps track of where you

197
00:08:44.919 --> 00:08:47.279
<v Speaker 2>are in the sequence and gives you the next element

198
00:08:47.279 --> 00:08:48.039
<v Speaker 2>when you ask for it.

199
00:08:48.240 --> 00:08:51.559
<v Speaker 1>So the iterable is the data source and the iterator

200
00:08:51.639 --> 00:08:53.840
<v Speaker 1>is like a cursor moving through that data.

201
00:08:53.879 --> 00:08:56.879
<v Speaker 2>A perfect analogy. And in Python you can get an

202
00:08:56.919 --> 00:09:00.360
<v Speaker 2>iterator from an iterable using the itter function, and then

203
00:09:00.360 --> 00:09:02.480
<v Speaker 2>you use the next function to fetch the next element.

204
00:09:02.600 --> 00:09:05.200
<v Speaker 1>And what about that stop iteration exception I've seen.

205
00:09:05.279 --> 00:09:07.679
<v Speaker 2>Ah yeah, that just means the iterator has reached the

206
00:09:07.759 --> 00:09:10.279
<v Speaker 2>end of the sequence, like reaching the last page as

207
00:09:10.320 --> 00:09:10.639
<v Speaker 2>a book.

208
00:09:10.679 --> 00:09:13.559
<v Speaker 1>Okay, that makes sense. Now how do generators fit into

209
00:09:13.559 --> 00:09:14.120
<v Speaker 1>this picture?

210
00:09:14.399 --> 00:09:17.799
<v Speaker 2>Think of generators as iterators with a memory saving superpower.

211
00:09:19.120 --> 00:09:21.639
<v Speaker 2>They don't generate all the values up front, They produce

212
00:09:21.720 --> 00:09:23.720
<v Speaker 2>them one at a time on demand.

213
00:09:23.960 --> 00:09:25.759
<v Speaker 1>So it's like having a recipe that tells you how

214
00:09:25.799 --> 00:09:27.639
<v Speaker 1>to make each dish as you need it instead of

215
00:09:27.639 --> 00:09:29.720
<v Speaker 1>cooking everything in advance and letting it go cold.

216
00:09:29.919 --> 00:09:32.240
<v Speaker 2>That's a great way to put it. It's super efficient,

217
00:09:32.360 --> 00:09:34.240
<v Speaker 2>especially if you're working with large data sets.

218
00:09:34.360 --> 00:09:36.960
<v Speaker 1>Okay, generators are starting to click from it now. And

219
00:09:37.120 --> 00:09:40.120
<v Speaker 1>Python two oh one mentions a module called itter tools,

220
00:09:40.200 --> 00:09:42.600
<v Speaker 1>which is like a toolbox for working with iterators.

221
00:09:42.679 --> 00:09:45.200
<v Speaker 2>Itter tools is awesome. It's packed with all these pre

222
00:09:45.279 --> 00:09:48.240
<v Speaker 2>built iterators that you can mix and match to create

223
00:09:48.320 --> 00:09:49.399
<v Speaker 2>really powerful code.

224
00:09:49.720 --> 00:09:52.000
<v Speaker 1>Sounds dangerous. What are some of the highlights.

225
00:09:52.080 --> 00:09:55.279
<v Speaker 2>Well, there's count, which can generate an endless sequence of numbers.

226
00:09:55.399 --> 00:09:58.080
<v Speaker 2>Page sixty two has a simple example using.

227
00:09:57.879 --> 00:10:00.000
<v Speaker 1>Count lines one in two, right, yep.

228
00:10:00.360 --> 00:10:03.720
<v Speaker 2>And then there's cycle, which endlessly loops through an iterable.

229
00:10:04.080 --> 00:10:06.799
<v Speaker 2>It's great for things like round robin scheduling, or anything

230
00:10:06.799 --> 00:10:08.879
<v Speaker 2>where you need to keep repeating a sequence.

231
00:10:09.000 --> 00:10:10.840
<v Speaker 1>Okay, I can see how that could be useful. Where's

232
00:10:10.840 --> 00:10:11.879
<v Speaker 1>the example for cycle.

233
00:10:12.000 --> 00:10:13.879
<v Speaker 2>It's on page sixty three, lines one in three.

234
00:10:14.000 --> 00:10:16.000
<v Speaker 1>Got it? What else is in there?

235
00:10:16.159 --> 00:10:18.600
<v Speaker 2>Group B is a really powerful one. It lets you

236
00:10:18.600 --> 00:10:21.720
<v Speaker 2>group consecutive items in an iterable based on a key,

237
00:10:22.080 --> 00:10:23.720
<v Speaker 2>Like if you have a list of transactions, you could

238
00:10:23.720 --> 00:10:25.480
<v Speaker 2>group them by date or by customer.

239
00:10:25.720 --> 00:10:29.039
<v Speaker 1>Ooh, that sounds perfect for data analysis. I see they

240
00:10:29.120 --> 00:10:32.360
<v Speaker 1>use group B to group vehicles by make. On page sixty.

241
00:10:32.080 --> 00:10:34.240
<v Speaker 2>Eight right, lines one and nine show how to use

242
00:10:34.279 --> 00:10:37.000
<v Speaker 2>group B, and then lines ten and thirteen show how

243
00:10:37.039 --> 00:10:37.960
<v Speaker 2>to access the groups.

244
00:10:38.080 --> 00:10:40.799
<v Speaker 1>This is making me realize how often I've written custom

245
00:10:40.840 --> 00:10:43.440
<v Speaker 1>code to do things that iter tools can already do

246
00:10:43.559 --> 00:10:43.799
<v Speaker 1>for me.

247
00:10:44.000 --> 00:10:46.159
<v Speaker 2>Huh huh. Yeah, it's a real timesaver once you get

248
00:10:46.159 --> 00:10:46.559
<v Speaker 2>the hang of it.

249
00:10:47.000 --> 00:10:49.039
<v Speaker 1>Last one, and I'm just going by your notes, here

250
00:10:49.200 --> 00:10:49.879
<v Speaker 1>is product.

251
00:10:50.080 --> 00:10:52.600
<v Speaker 2>Oh yeah. Product is a fun one. It generates all

252
00:10:52.720 --> 00:10:57.080
<v Speaker 2>possible combinations of elements from multiple iterables. It's like a

253
00:10:57.120 --> 00:10:58.440
<v Speaker 2>combinatorial explosion.

254
00:10:58.600 --> 00:11:00.320
<v Speaker 1>Sounds intense. Is there an example for one?

255
00:11:00.399 --> 00:11:02.720
<v Speaker 2>It's on page seventy just a single line of code

256
00:11:02.720 --> 00:11:04.519
<v Speaker 2>to demonstrate the power of combinations.

257
00:11:04.639 --> 00:11:07.399
<v Speaker 1>Okay, I'm definitely adding iter tools to my list of

258
00:11:07.440 --> 00:11:09.960
<v Speaker 1>modules to explore further. It's like a secret weapon for

259
00:11:10.080 --> 00:11:11.519
<v Speaker 1>data manipulation in Python.

260
00:11:11.799 --> 00:11:14.919
<v Speaker 2>It really is. All Right, we've talked a lot about modules.

261
00:11:15.080 --> 00:11:17.480
<v Speaker 2>Let's switch gears a bit and talk about unicode. It's

262
00:11:17.519 --> 00:11:20.759
<v Speaker 2>such a fundamental concept when working with text in Python,

263
00:11:21.039 --> 00:11:22.480
<v Speaker 2>but it can also be a bit confusing.

264
00:11:22.720 --> 00:11:25.440
<v Speaker 1>Yeah. I've definitely run into some character encoding issues in

265
00:11:25.440 --> 00:11:27.159
<v Speaker 1>the past that made me pull my hair out.

266
00:11:27.519 --> 00:11:31.320
<v Speaker 2>Unicode is all about representing characters from every language in

267
00:11:31.360 --> 00:11:33.399
<v Speaker 2>the world in a consistent way.

268
00:11:33.440 --> 00:11:36.159
<v Speaker 1>So it's like a universal language for characters.

269
00:11:36.600 --> 00:11:38.720
<v Speaker 2>That's a good way to think about it. It helps

270
00:11:38.720 --> 00:11:42.120
<v Speaker 2>to avoid those annoying encoding errors and ensures that your

271
00:11:42.159 --> 00:11:45.320
<v Speaker 2>text is displayed correctly no matter what language it's in.

272
00:11:45.720 --> 00:11:50.480
<v Speaker 1>The book mentions something called Unicode decode error on page ninety.

273
00:11:50.240 --> 00:11:52.679
<v Speaker 2>Nine, Right, that's an error you might encounter if you

274
00:11:52.720 --> 00:11:55.320
<v Speaker 2>try to work with text that's not properly encoded.

275
00:11:55.559 --> 00:11:58.559
<v Speaker 1>So if I'm reading data from a file or the web,

276
00:11:58.639 --> 00:12:00.759
<v Speaker 1>I need to be careful about how it's coded and

277
00:12:00.840 --> 00:12:03.799
<v Speaker 1>use the decode method to convert it to Unicode correctly.

278
00:12:04.039 --> 00:12:06.759
<v Speaker 2>You got it. The ignore and replaced flags can be

279
00:12:06.840 --> 00:12:08.600
<v Speaker 2>handy for dealing with tricky characters.

280
00:12:08.840 --> 00:12:11.919
<v Speaker 1>This is making me appreciate the importance of understanding Unicode.

281
00:12:12.039 --> 00:12:14.440
<v Speaker 1>It's like the foundation for working with text in a

282
00:12:14.480 --> 00:12:15.519
<v Speaker 1>globalized world.

283
00:12:15.759 --> 00:12:18.960
<v Speaker 2>Absolutely, okay. One last concept for this part of our

284
00:12:18.960 --> 00:12:22.600
<v Speaker 2>deep dive benchmarking AH benchmarking.

285
00:12:22.639 --> 00:12:25.399
<v Speaker 1>That's about measuring code performance, right exactly.

286
00:12:25.440 --> 00:12:28.960
<v Speaker 2>It's about figuring out how fast your code runs and

287
00:12:29.039 --> 00:12:31.080
<v Speaker 2>identifying areas where you can make it faster.

288
00:12:31.279 --> 00:12:33.720
<v Speaker 1>So it's not just about writing code that works, it's

289
00:12:33.759 --> 00:12:35.840
<v Speaker 1>about writing code that works efficiently.

290
00:12:36.320 --> 00:12:38.720
<v Speaker 2>You got it. Python two one covers a few different

291
00:12:38.720 --> 00:12:42.360
<v Speaker 2>tools for benchmarking. There's timite, which is great for measuring

292
00:12:42.360 --> 00:12:44.559
<v Speaker 2>the execution time of small pieces of code.

293
00:12:44.720 --> 00:12:47.279
<v Speaker 1>I've heard of timeite, but never really used it. What's

294
00:12:47.320 --> 00:12:47.759
<v Speaker 1>it good for?

295
00:12:47.919 --> 00:12:50.919
<v Speaker 2>It's perfect for those times when you have a function

296
00:12:51.120 --> 00:12:53.320
<v Speaker 2>or a block of code that seems to be running slow.

297
00:12:54.080 --> 00:12:56.919
<v Speaker 2>You can use timite to pinpoint exactly how slow it

298
00:12:56.960 --> 00:12:58.519
<v Speaker 2>is and where the bottleneck might be.

299
00:12:58.600 --> 00:13:01.120
<v Speaker 1>Okay, that makes sense. What about profile? Is that for

300
00:13:01.200 --> 00:13:02.480
<v Speaker 1>profiling entire programs?

301
00:13:02.519 --> 00:13:05.159
<v Speaker 2>You got it? Ce Profile gives you a detailed report

302
00:13:05.200 --> 00:13:07.720
<v Speaker 2>of how much time is spent in each function call

303
00:13:07.799 --> 00:13:10.200
<v Speaker 2>within your program. You can run it from the command

304
00:13:10.240 --> 00:13:13.320
<v Speaker 2>line as mentioned on page one oh six, line one, so.

305
00:13:13.240 --> 00:13:15.360
<v Speaker 1>It's like an X ray for your code, showing you

306
00:13:15.440 --> 00:13:16.840
<v Speaker 1>where all the time is being spent.

307
00:13:17.200 --> 00:13:20.399
<v Speaker 2>And finally, there's line profiler, which takes things to a

308
00:13:20.440 --> 00:13:23.159
<v Speaker 2>whole new level. It actually shows you how much time

309
00:13:23.240 --> 00:13:25.480
<v Speaker 2>is spent on each individual line of code.

310
00:13:25.519 --> 00:13:27.519
<v Speaker 1>WHOA, that's granular. How does it work?

311
00:13:27.720 --> 00:13:30.240
<v Speaker 2>You use the current prop script and the app profile

312
00:13:30.279 --> 00:13:32.879
<v Speaker 2>decorator is shown on page one oh seven to instrument

313
00:13:32.879 --> 00:13:34.799
<v Speaker 2>your code. Then you can run it and get a

314
00:13:34.799 --> 00:13:36.320
<v Speaker 2>line by line breakdown of performance.

315
00:13:36.399 --> 00:13:38.879
<v Speaker 1>That's amazing. It's like having a magnifying glass for your

316
00:13:38.960 --> 00:13:39.799
<v Speaker 1>code performance.

317
00:13:39.919 --> 00:13:42.600
<v Speaker 2>It can be super helpful for finding those subtle performance

318
00:13:42.600 --> 00:13:44.759
<v Speaker 2>bottlenecks that you might not otherwise notice.

319
00:13:44.840 --> 00:13:47.720
<v Speaker 1>Okay, I'm feeling inspired to go and profile all my

320
00:13:47.799 --> 00:13:50.200
<v Speaker 1>Python code now. I think we've covered a lot of

321
00:13:50.279 --> 00:13:52.519
<v Speaker 1>ground in this first part of our Python two oh

322
00:13:52.519 --> 00:13:57.399
<v Speaker 1>one deep dive. We've explored modules like art parse, collections, contextlib,

323
00:13:57.480 --> 00:14:02.759
<v Speaker 1>funct tools, and import lib. We've delved into iterators, generators, Unicode,

324
00:14:02.919 --> 00:14:04.840
<v Speaker 1>and even touched on benchmarking.

325
00:14:04.960 --> 00:14:07.759
<v Speaker 2>We've barely scratched the surface, though, there's so much more

326
00:14:07.799 --> 00:14:10.679
<v Speaker 2>to uncover in Python two oh one. Next time, we'll

327
00:14:10.720 --> 00:14:13.600
<v Speaker 2>dive into the world of regular expressions, type hinting, and

328
00:14:13.679 --> 00:14:16.519
<v Speaker 2>the powerful super built in. Get ready for another round

329
00:14:16.519 --> 00:14:17.600
<v Speaker 2>of Python awesomeness.

330
00:14:17.879 --> 00:14:21.279
<v Speaker 1>Back for more Python fun. Last time, we dug into

331
00:14:21.320 --> 00:14:24.559
<v Speaker 1>some awesome modules and really got to handle on iterators

332
00:14:24.559 --> 00:14:28.159
<v Speaker 1>and generators. What's next on our Python two oh one journey.

333
00:14:28.519 --> 00:14:31.799
<v Speaker 2>Let's explore the world of regular expressions, or, as the

334
00:14:31.799 --> 00:14:33.440
<v Speaker 2>cool kids call it, rejects.

335
00:14:33.919 --> 00:14:36.519
<v Speaker 1>Jacts. I've seen them, those strings of characters that look

336
00:14:36.600 --> 00:14:38.080
<v Speaker 1>like they're straight out of the matrix.

337
00:14:38.200 --> 00:14:40.879
<v Speaker 2>They can seem a bit crypic at first, but trust me,

338
00:14:41.240 --> 00:14:43.519
<v Speaker 2>once you get the basics, rejex is like having a

339
00:14:43.600 --> 00:14:47.039
<v Speaker 2>superpower for working with text. Python two oh one breaks

340
00:14:47.080 --> 00:14:47.840
<v Speaker 2>it down really well.

341
00:14:47.960 --> 00:14:50.120
<v Speaker 1>Okay, I'm willing to give it another shot. What are

342
00:14:50.159 --> 00:14:51.879
<v Speaker 1>the building blocks of rejects?

343
00:14:51.960 --> 00:14:54.519
<v Speaker 2>Well, it all starts with meta characters. They're kind of

344
00:14:54.559 --> 00:14:58.480
<v Speaker 2>like special characters, but they represent patterns rather than literal characters.

345
00:14:58.679 --> 00:15:02.200
<v Speaker 1>So instead of matchings, say the letter A, you can

346
00:15:02.240 --> 00:15:04.000
<v Speaker 1>match a whole category.

347
00:15:03.480 --> 00:15:06.960
<v Speaker 2>Of characters, exactly like the dot can match any character

348
00:15:07.000 --> 00:15:09.320
<v Speaker 2>except a new line. Page seventy six of the book

349
00:15:09.320 --> 00:15:10.320
<v Speaker 2>has a bunch of examples.

350
00:15:10.360 --> 00:15:12.399
<v Speaker 1>Okay, I'm starting to see how this could be powerful.

351
00:15:12.600 --> 00:15:15.200
<v Speaker 1>What if I want to match a specific set of characters,

352
00:15:15.240 --> 00:15:16.639
<v Speaker 1>like all the lowercase letters.

353
00:15:16.919 --> 00:15:19.600
<v Speaker 2>That's where character classes come in. You put the characters

354
00:15:19.600 --> 00:15:23.080
<v Speaker 2>you want to match inside square brackets, like AZ would

355
00:15:23.120 --> 00:15:26.360
<v Speaker 2>match any lowercase letter and zero nine would match any digit.

356
00:15:26.639 --> 00:15:29.080
<v Speaker 1>Makes sense. Page seventy seven talks more about that.

357
00:15:29.080 --> 00:15:31.720
<v Speaker 2>Right, That's the one They go into detail about character

358
00:15:31.759 --> 00:15:34.159
<v Speaker 2>classes and all the different ways you can use them now.

359
00:15:34.159 --> 00:15:37.240
<v Speaker 2>Another important part of rejects is quantifiers. They let you

360
00:15:37.240 --> 00:15:40.120
<v Speaker 2>control how many times a character or a pattern should appear.

361
00:15:40.279 --> 00:15:41.919
<v Speaker 1>No, that's handy, Like if I want to match a

362
00:15:41.960 --> 00:15:43.480
<v Speaker 1>word that appears at least three.

363
00:15:43.279 --> 00:15:46.240
<v Speaker 2>Times, You got it. There's the asterisk for zero or

364
00:15:46.279 --> 00:15:49.879
<v Speaker 2>more occurrences, the plus sign plus for one or more,

365
00:15:50.279 --> 00:15:52.679
<v Speaker 2>and the question mark for zero or one.

366
00:15:53.000 --> 00:15:56.120
<v Speaker 1>So much control packed into just a few symbols. Now,

367
00:15:56.120 --> 00:15:59.279
<v Speaker 1>Python has the remodule for working with rejects.

368
00:15:58.960 --> 00:16:01.600
<v Speaker 2>Right absolutely. The remodule gives you all the tools you

369
00:16:01.679 --> 00:16:05.919
<v Speaker 2>need to search, match, and manipulate strings using rejects. It's

370
00:16:05.919 --> 00:16:07.440
<v Speaker 2>your reject Swiss army knife.

371
00:16:07.639 --> 00:16:12.080
<v Speaker 1>Cool. You've highlighted some lines from page seventy nine, lines eight, nine, ten, twelve,

372
00:16:12.080 --> 00:16:12.679
<v Speaker 1>and thirteen.

373
00:16:13.080 --> 00:16:15.840
<v Speaker 2>Those lines show how to use the redot search function

374
00:16:16.279 --> 00:16:18.799
<v Speaker 2>to find a pattern in a string. It returns a

375
00:16:18.840 --> 00:16:20.960
<v Speaker 2>match object if the pattern is found.

376
00:16:20.879 --> 00:16:23.720
<v Speaker 1>So line eight defines the reject pattern, line nine does

377
00:16:23.759 --> 00:16:25.759
<v Speaker 1>the search, and then the other lines show how to

378
00:16:25.799 --> 00:16:28.039
<v Speaker 1>extract information from the match object.

379
00:16:28.279 --> 00:16:31.320
<v Speaker 2>Exactly you can get the match text it's positioned in

380
00:16:31.360 --> 00:16:33.879
<v Speaker 2>the string, and all sorts of other useful details. And

381
00:16:33.919 --> 00:16:36.919
<v Speaker 2>on page eighty Python two oh one shows how to

382
00:16:36.960 --> 00:16:40.840
<v Speaker 2>compile rejects patterns for better performance using redot compile.

383
00:16:41.200 --> 00:16:43.039
<v Speaker 1>Ah. So, if I'm going to be using the same

384
00:16:43.080 --> 00:16:46.360
<v Speaker 1>pattern multiple times, it makes sense to compile it once

385
00:16:46.639 --> 00:16:48.480
<v Speaker 1>and then reuse the compiled object.

386
00:16:48.679 --> 00:16:50.440
<v Speaker 2>It's like caching the pattern so you don't have to

387
00:16:50.519 --> 00:16:52.759
<v Speaker 2>keep recompiling it over and over. It can really speed

388
00:16:52.799 --> 00:16:53.240
<v Speaker 2>things up.

389
00:16:53.320 --> 00:16:55.639
<v Speaker 1>I'm starting to feel more confident about rejects now. It's

390
00:16:55.679 --> 00:16:59.480
<v Speaker 1>really just about understanding those core components and then using

391
00:16:59.559 --> 00:17:01.399
<v Speaker 1>the remark to put them into action.

392
00:17:01.600 --> 00:17:03.559
<v Speaker 2>You're getting it. With a little practice, You'll be a

393
00:17:03.559 --> 00:17:06.640
<v Speaker 2>retext wizard in no time. Okay, okay, ready to switch

394
00:17:06.680 --> 00:17:07.079
<v Speaker 2>gears again.

395
00:17:07.240 --> 00:17:07.559
<v Speaker 1>Hit me.

396
00:17:07.880 --> 00:17:10.559
<v Speaker 2>Let's talk about type hinting. It's a feature that was

397
00:17:10.599 --> 00:17:13.160
<v Speaker 2>added in Python three point five, and it's all about

398
00:17:13.200 --> 00:17:15.319
<v Speaker 2>making your code more explicit and robust.

399
00:17:15.640 --> 00:17:16.680
<v Speaker 1>Explicit in what way?

400
00:17:16.880 --> 00:17:20.359
<v Speaker 2>Well, you know how Python is dynamically typed, meaning the

401
00:17:20.440 --> 00:17:22.400
<v Speaker 2>types of variables are checked at run time.

402
00:17:22.759 --> 00:17:24.640
<v Speaker 1>Yeah, that's one of the things I love about Python.

403
00:17:24.680 --> 00:17:26.279
<v Speaker 1>It's so flexible it is.

404
00:17:26.920 --> 00:17:30.720
<v Speaker 2>But sometimes that flexibility can lead to unexpected errors, especially

405
00:17:30.720 --> 00:17:31.759
<v Speaker 2>in larger projects.

406
00:17:32.000 --> 00:17:34.359
<v Speaker 1>I've definitely been bitten by that a few times.

407
00:17:34.480 --> 00:17:37.440
<v Speaker 2>Well, type hinting lets you add annotations to your code

408
00:17:37.440 --> 00:17:40.920
<v Speaker 2>that indicate the expected types of variables, function arguments, and

409
00:17:41.000 --> 00:17:41.880
<v Speaker 2>return values.

410
00:17:42.000 --> 00:17:45.279
<v Speaker 1>So even though Python is still dynamically typed i can

411
00:17:45.319 --> 00:17:48.640
<v Speaker 1>add these hints to help catch potential type errors before

412
00:17:48.680 --> 00:17:49.200
<v Speaker 1>they happen.

413
00:17:49.480 --> 00:17:52.079
<v Speaker 2>Exactly. It's like adding a safety net to your code,

414
00:17:52.920 --> 00:17:55.720
<v Speaker 2>and tools like my pie can actually use these type

415
00:17:55.759 --> 00:17:59.680
<v Speaker 2>hints to do static analysis and flag potential.

416
00:17:59.240 --> 00:18:03.079
<v Speaker 1>Issues incredibly valuable. Page eighty five of Python two to

417
00:18:03.240 --> 00:18:05.400
<v Speaker 1>one shows a simple example of type hinting.

418
00:18:05.680 --> 00:18:09.480
<v Speaker 2>Right line six, nine and twelve demonstrate how to add

419
00:18:09.519 --> 00:18:12.400
<v Speaker 2>type pints to a function that calculates the area of

420
00:18:12.400 --> 00:18:13.119
<v Speaker 2>a rectangle.

421
00:18:13.519 --> 00:18:15.799
<v Speaker 1>So they're specifying that the width and height should be

422
00:18:15.839 --> 00:18:18.400
<v Speaker 1>slots and that the return value should also be afloat.

423
00:18:18.480 --> 00:18:20.759
<v Speaker 2>It makes the code more readable and it helps tools

424
00:18:20.799 --> 00:18:23.920
<v Speaker 2>like mypi verify that the types are being used correctly.

425
00:18:24.079 --> 00:18:27.200
<v Speaker 1>It's like adding documentation to your code that the computer

426
00:18:27.279 --> 00:18:28.680
<v Speaker 1>can actually understand and use.

427
00:18:28.920 --> 00:18:30.279
<v Speaker 2>That's a great way to put it, and you can

428
00:18:30.400 --> 00:18:34.519
<v Speaker 2>use type penting with more complex data structures too, like lists, dictionaries,

429
00:18:34.559 --> 00:18:35.720
<v Speaker 2>and custom classes.

430
00:18:35.960 --> 00:18:39.519
<v Speaker 1>Speaking of Python twoh one also mentions using type pinting

431
00:18:39.599 --> 00:18:42.799
<v Speaker 1>with overloaded functions. You know those functions that can handle

432
00:18:42.880 --> 00:18:43.880
<v Speaker 1>different input types.

433
00:18:44.000 --> 00:18:46.920
<v Speaker 2>Yeah, type pending is a perfect fit for overloaded functions.

434
00:18:47.119 --> 00:18:50.240
<v Speaker 2>It lets you provide specific type signatures for each variation

435
00:18:50.319 --> 00:18:52.759
<v Speaker 2>of the function, so it's clear what types are expected

436
00:18:52.759 --> 00:18:53.880
<v Speaker 2>and what type is returned.

437
00:18:53.960 --> 00:18:56.960
<v Speaker 1>They revisit the ad function example on page eighty seven

438
00:18:57.039 --> 00:18:59.920
<v Speaker 1>and show how to add type pints to the overloaded versions.

439
00:19:00.079 --> 00:19:02.079
<v Speaker 2>Each version of AD now has its own set of

440
00:19:02.079 --> 00:19:05.160
<v Speaker 2>type annotations, making it super clear how each one should

441
00:19:05.160 --> 00:19:05.559
<v Speaker 2>be used.

442
00:19:05.839 --> 00:19:08.359
<v Speaker 1>Type hinting is definitely a game changer. I'm going to

443
00:19:08.400 --> 00:19:11.160
<v Speaker 1>have to start using it more in my own code. Okay.

444
00:19:11.200 --> 00:19:14.920
<v Speaker 1>One last concept from Python two to oh one the

445
00:19:15.039 --> 00:19:18.039
<v Speaker 1>super built in I've always been a bit mystified by super.

446
00:19:18.279 --> 00:19:21.039
<v Speaker 2>Super can be a bit tricky, but it's a really

447
00:19:21.079 --> 00:19:24.519
<v Speaker 2>powerful tool when you're working with inheritance in Python.

448
00:19:24.640 --> 00:19:29.519
<v Speaker 1>Inheritance that's where you create new classes based on existing ones, right, you.

449
00:19:29.519 --> 00:19:33.079
<v Speaker 2>Got it, and super provides a way to access methods

450
00:19:33.079 --> 00:19:36.599
<v Speaker 2>from parent classes without having to explicitly name them.

451
00:19:36.680 --> 00:19:39.960
<v Speaker 1>So it's like a shortcut for calling parent class methods.

452
00:19:39.599 --> 00:19:41.839
<v Speaker 2>And more than just a shortcut, it makes your code

453
00:19:41.920 --> 00:19:44.839
<v Speaker 2>more flexible and maintainable because you don't have to hardcode

454
00:19:44.839 --> 00:19:46.279
<v Speaker 2>the parent class name everywhere.

455
00:19:46.400 --> 00:19:48.279
<v Speaker 1>The example on page one thirty four shows how to

456
00:19:48.359 --> 00:19:51.759
<v Speaker 1>use super within a subclass constructor. Right lines three and

457
00:19:51.839 --> 00:19:52.759
<v Speaker 1>six are highlighted.

458
00:19:53.000 --> 00:19:55.279
<v Speaker 2>Those lines show how to call the constructor of the

459
00:19:55.319 --> 00:19:58.519
<v Speaker 2>parent class using super. It's a very common use case.

460
00:19:58.759 --> 00:20:00.880
<v Speaker 1>So in line three they're get a reference to the

461
00:20:00.880 --> 00:20:03.480
<v Speaker 1>parent class using super, and then in line six they're

462
00:20:03.559 --> 00:20:06.240
<v Speaker 1>using that reference to call the parent class's constructor.

463
00:20:06.359 --> 00:20:08.480
<v Speaker 2>You got it. It's a clean and elegant way to

464
00:20:08.519 --> 00:20:09.480
<v Speaker 2>handle inheritance.

465
00:20:09.680 --> 00:20:12.640
<v Speaker 1>I'm starting to see how super can simplify things, especially

466
00:20:12.680 --> 00:20:16.359
<v Speaker 1>in complex class hierarchies. Okay, we've covered a lot of

467
00:20:16.359 --> 00:20:18.319
<v Speaker 1>ground in the second part of our Python two oh

468
00:20:18.319 --> 00:20:21.200
<v Speaker 1>one deep dive, from the power of rejects to the

469
00:20:21.200 --> 00:20:24.559
<v Speaker 1>clarity of type hinting and the flexibility of super. It's

470
00:20:24.599 --> 00:20:26.039
<v Speaker 1>been another amazing.

471
00:20:25.759 --> 00:20:29.559
<v Speaker 2>Journey, and there's still more to come. In the final part,

472
00:20:29.720 --> 00:20:32.960
<v Speaker 2>we'll venture into the world of descriptors, delve deeper into

473
00:20:32.960 --> 00:20:36.039
<v Speaker 2>the nuances of scope in Python, and maybe even uncover

474
00:20:36.119 --> 00:20:39.039
<v Speaker 2>a few hidden gems along the way. Stay tuned for

475
00:20:39.079 --> 00:20:40.119
<v Speaker 2>the grand finale.

476
00:20:40.319 --> 00:20:42.920
<v Speaker 1>We're back ready to wrap up our Python two oh

477
00:20:43.039 --> 00:20:47.400
<v Speaker 1>one deep dive. We've covered some really cool stuff. Modules, iterators,

478
00:20:47.480 --> 00:20:50.839
<v Speaker 1>rejects type hinting, but I know there are still some

479
00:20:50.920 --> 00:20:53.519
<v Speaker 1>corners of Python twoh one we haven't explored yet.

480
00:20:53.680 --> 00:20:55.960
<v Speaker 2>You're right, there are a few more gems to uncover,

481
00:20:56.440 --> 00:20:58.200
<v Speaker 2>and today we're going to go deep into some of

482
00:20:58.240 --> 00:21:01.799
<v Speaker 2>the more subtle but incredibly important aspects of Python. Let's

483
00:21:01.839 --> 00:21:02.799
<v Speaker 2>start with descriptors.

484
00:21:03.039 --> 00:21:05.119
<v Speaker 1>Descriptors. I remember that term from the book, but I'll

485
00:21:05.160 --> 00:21:06.799
<v Speaker 1>be honest, they always kind of mystified me.

486
00:21:07.119 --> 00:21:10.119
<v Speaker 2>I get it. Descriptors work behind the scenes, but they

487
00:21:10.160 --> 00:21:12.960
<v Speaker 2>play a crucial role in how we access and manage

488
00:21:12.960 --> 00:21:17.160
<v Speaker 2>attributes in Python. They're like intermediaries for attribute access.

489
00:21:17.319 --> 00:21:20.440
<v Speaker 1>So instead of directly getting or setting an attributes value,

490
00:21:20.519 --> 00:21:22.319
<v Speaker 1>you go through a descriptor. Why do we need that

491
00:21:22.400 --> 00:21:23.039
<v Speaker 1>extra layer?

492
00:21:23.279 --> 00:21:26.799
<v Speaker 2>Descriptors give you a way to customize attribute behavior beyond

493
00:21:26.960 --> 00:21:30.519
<v Speaker 2>just getting and setting. You can add logic for validation, logging,

494
00:21:30.799 --> 00:21:32.759
<v Speaker 2>or even lazy loading of attributes.

495
00:21:33.000 --> 00:21:36.160
<v Speaker 1>Ah. So it's like adding a layer of intelligence to attributes.

496
00:21:36.200 --> 00:21:39.920
<v Speaker 1>I remember Python two one mentioning something about special methods.

497
00:21:40.160 --> 00:21:44.160
<v Speaker 2>Yes, descriptors use the get, set, and delete methods to

498
00:21:44.240 --> 00:21:48.519
<v Speaker 2>define their behavior. There are data descriptors which implement both

499
00:21:48.559 --> 00:21:51.880
<v Speaker 2>get and set, and non data descriptors which usually just

500
00:21:51.920 --> 00:21:53.279
<v Speaker 2>implement get so.

501
00:21:53.319 --> 00:21:56.799
<v Speaker 1>Data descriptors control both reading and writing attributes, while non

502
00:21:56.880 --> 00:21:59.960
<v Speaker 1>data descriptors are more about controlling access exactly.

503
00:22:00.319 --> 00:22:03.000
<v Speaker 2>And what's really interesting is that data descriptors actually take

504
00:22:03.279 --> 00:22:07.160
<v Speaker 2>precedence over the instance dictionary. So even if you try

505
00:22:07.160 --> 00:22:10.359
<v Speaker 2>to directly access and attribute on an object, if there's

506
00:22:10.359 --> 00:22:13.720
<v Speaker 2>a data descriptor for that attribute, its logic will override

507
00:22:13.759 --> 00:22:15.200
<v Speaker 2>any direct access.

508
00:22:14.799 --> 00:22:16.839
<v Speaker 1>So the descriptor always wins. That's good to know.

509
00:22:16.960 --> 00:22:20.160
<v Speaker 2>It ensures consistency and control over how attributes are handled.

510
00:22:20.240 --> 00:22:22.039
<v Speaker 2>There's a great example in the book on page one

511
00:22:22.079 --> 00:22:25.000
<v Speaker 2>thirty eight. They create a custom descriptor that logs every

512
00:22:25.079 --> 00:22:26.519
<v Speaker 2>time an attribute is accessed.

513
00:22:26.759 --> 00:22:30.559
<v Speaker 1>Lines five, nine, thirteen, and eighteen are highlighted in my copy.

514
00:22:30.680 --> 00:22:33.079
<v Speaker 2>Those lines show the implementation of the descriptor and how

515
00:22:33.079 --> 00:22:35.960
<v Speaker 2>it logs each access. It's a clever way to track

516
00:22:36.039 --> 00:22:39.920
<v Speaker 2>attribute usage or enforce specific rules without cluttering up your

517
00:22:39.920 --> 00:22:40.519
<v Speaker 2>main code.

518
00:22:40.559 --> 00:22:42.559
<v Speaker 1>I like it. It's like having a little watchdog for

519
00:22:42.599 --> 00:22:46.759
<v Speaker 1>your attributes. Now. Python two one connects to scriptors to

520
00:22:46.799 --> 00:22:50.079
<v Speaker 1>the concept of scope in Python. Can you explain that connection.

521
00:22:50.519 --> 00:22:53.839
<v Speaker 2>Scope at its core is all about determining where a

522
00:22:53.880 --> 00:22:58.039
<v Speaker 2>particular variable or name is visible and accessible in your code.

523
00:22:58.480 --> 00:23:02.240
<v Speaker 2>Python has local scope, global scope, and you guess it

524
00:23:02.720 --> 00:23:03.960
<v Speaker 2>non local scope.

525
00:23:03.880 --> 00:23:07.240
<v Speaker 1>Right, I remember learning about local and global scope. Local

526
00:23:07.319 --> 00:23:10.359
<v Speaker 1>variables are confined to a function, while global variables can

527
00:23:10.359 --> 00:23:12.240
<v Speaker 1>be accessed from anywhere. It tripped me up a few

528
00:23:12.240 --> 00:23:13.319
<v Speaker 1>times when I was starting out.

529
00:23:13.400 --> 00:23:16.000
<v Speaker 2>Yeah, it's a common stumbling block. And then Python three

530
00:23:16.079 --> 00:23:19.599
<v Speaker 2>added non local scope, which throws another wrench into the works,

531
00:23:19.920 --> 00:23:22.000
<v Speaker 2>or should I say, another tool into the toolbox.

532
00:23:22.079 --> 00:23:23.720
<v Speaker 1>So what's non local scope all about?

533
00:23:23.920 --> 00:23:26.480
<v Speaker 2>The non local keyword, which is explained on page one

534
00:23:26.559 --> 00:23:29.000
<v Speaker 2>forty five of the book. Lets you modify variables in

535
00:23:29.039 --> 00:23:32.519
<v Speaker 2>an enclosing scope that are not global. It's especially useful

536
00:23:32.519 --> 00:23:34.000
<v Speaker 2>when you're working with nested functions.

537
00:23:34.319 --> 00:23:37.359
<v Speaker 1>Nested functions those are functions inside other functions.

538
00:23:37.000 --> 00:23:39.599
<v Speaker 2>Right yep. And non local lets you reach out from

539
00:23:39.599 --> 00:23:42.440
<v Speaker 2>an inner function and modify a variable in the out

540
00:23:42.440 --> 00:23:44.680
<v Speaker 2>of sunction without making it a global variable.

541
00:23:44.759 --> 00:23:47.039
<v Speaker 1>Hmm, I can see how that could be useful. The

542
00:23:47.039 --> 00:23:48.720
<v Speaker 1>book has an example of this, right.

543
00:23:48.759 --> 00:23:51.039
<v Speaker 2>Yeah, on page one forty five that use non local

544
00:23:51.119 --> 00:23:55.200
<v Speaker 2>to implement a counterfunction using nested functions. It's a good

545
00:23:55.240 --> 00:23:57.839
<v Speaker 2>illustration of how non local works in practice.

546
00:23:58.000 --> 00:24:00.200
<v Speaker 1>This is making me realize how important it is to

547
00:24:00.279 --> 00:24:03.920
<v Speaker 1>really understand scope in Python. It's like knowing the boundaries

548
00:24:03.960 --> 00:24:05.680
<v Speaker 1>of your code's universe exactly.

549
00:24:06.240 --> 00:24:09.559
<v Speaker 2>Python two oh one goes beyond just explaining these concepts

550
00:24:09.559 --> 00:24:13.279
<v Speaker 2>in isolation, though. It connects them to real world scenarios

551
00:24:13.599 --> 00:24:17.319
<v Speaker 2>like database interactions, web scraping, and even cryptography.

552
00:24:17.480 --> 00:24:19.119
<v Speaker 1>That's what I love about this book. It doesn't just

553
00:24:19.160 --> 00:24:21.480
<v Speaker 1>throw a bunch of abstract concepts at you, it shows

554
00:24:21.480 --> 00:24:24.000
<v Speaker 1>you how to actually use them to solve practical problems.

555
00:24:24.079 --> 00:24:26.559
<v Speaker 2>It's all about bridging the gap between theory and practice

556
00:24:26.920 --> 00:24:29.279
<v Speaker 2>and empowering you to write better Python code.

557
00:24:29.359 --> 00:24:31.240
<v Speaker 1>Well, I think it's safe to say that our Python

558
00:24:31.279 --> 00:24:34.319
<v Speaker 1>twoh one deep Dive has been a resounding success. We've

559
00:24:34.359 --> 00:24:39.799
<v Speaker 1>explored modules, iterators, rejects, type hinting, descriptors, scope, The list

560
00:24:39.880 --> 00:24:42.039
<v Speaker 1>goes on and on. I feel like my Python skills

561
00:24:42.039 --> 00:24:43.319
<v Speaker 1>have leveled up significantly.

562
00:24:43.559 --> 00:24:46.759
<v Speaker 2>I'm so glad to hear that. But remember, the journey

563
00:24:46.799 --> 00:24:50.039
<v Speaker 2>of a Python developer is never truly over. There's always

564
00:24:50.039 --> 00:24:53.440
<v Speaker 2>more to learn, new libraries to discover, and exciting challenges

565
00:24:53.480 --> 00:24:57.000
<v Speaker 2>to tackle. So keep coding, keep experimenting, and keep that

566
00:24:57.039 --> 00:24:58.200
<v Speaker 2>Pythonic spirit alive.

567
00:24:58.319 --> 00:25:00.839
<v Speaker 1>Couldn't have set it better myself. All our listeners out there,

568
00:25:00.839 --> 00:25:02.880
<v Speaker 1>thanks for joining us on this deep dive into Python

569
00:25:02.920 --> 00:25:04.920
<v Speaker 1>two to one. Until next time, Happy coating,
