WEBVTT

1
00:00:00.160 --> 00:00:03.040
<v Speaker 1>Welcome to the deep Dive. We're the place that takes

2
00:00:03.120 --> 00:00:06.280
<v Speaker 1>complex source material and well gives you the shortcut to

3
00:00:06.320 --> 00:00:08.400
<v Speaker 1>knowing what's really going on. Today, we're digging into the

4
00:00:08.400 --> 00:00:12.960
<v Speaker 1>philosophy the why behind Python, arguably the most popular programming

5
00:00:13.000 --> 00:00:13.560
<v Speaker 1>language out.

6
00:00:13.439 --> 00:00:16.440
<v Speaker 2>There right now exactly, and our mission it's not just

7
00:00:16.600 --> 00:00:18.839
<v Speaker 2>you know, ticking off syntax rules. We've been looking at

8
00:00:18.839 --> 00:00:23.199
<v Speaker 2>so Mirage's work, the Pythonic Way, specifically the guide for architects.

9
00:00:23.440 --> 00:00:26.239
<v Speaker 2>We want to get inside that architectural mindset. Why is

10
00:00:26.280 --> 00:00:29.399
<v Speaker 2>Python designed this way? How do we leverage that elegance

11
00:00:29.960 --> 00:00:33.719
<v Speaker 2>for big enterprise applications that people can actually read and maintain.

12
00:00:34.079 --> 00:00:37.560
<v Speaker 1>Right We're diving deep into what Pythonic truly means, and

13
00:00:37.600 --> 00:00:39.479
<v Speaker 1>it seems to start with this core tension.

14
00:00:39.520 --> 00:00:44.479
<v Speaker 2>This balance, a balance between helpful abstraction hiding the complicated stuff,

15
00:00:44.840 --> 00:00:48.359
<v Speaker 2>and necessary access giving you the tools to break through

16
00:00:48.359 --> 00:00:50.600
<v Speaker 2>that abstraction when you really really need to.

17
00:00:50.679 --> 00:00:53.600
<v Speaker 1>Okay, So, abstraction versus access, how does that play out?

18
00:00:53.799 --> 00:00:56.799
<v Speaker 2>Well? It all stems from this core idea. The source

19
00:00:56.840 --> 00:01:00.039
<v Speaker 2>material calls need to know. The principle is basically, the

20
00:01:00.560 --> 00:01:04.959
<v Speaker 2>good software hides complexity. The aim is to let you

21
00:01:05.159 --> 00:01:08.280
<v Speaker 2>the developer, focus only on what you need for your

22
00:01:08.319 --> 00:01:11.040
<v Speaker 2>immediate task. It saves a ton of mental energy.

23
00:01:11.079 --> 00:01:13.400
<v Speaker 1>And there's that military analogy in the text which I

24
00:01:13.400 --> 00:01:14.439
<v Speaker 1>thought was quite striking.

25
00:01:14.519 --> 00:01:16.879
<v Speaker 2>Yeah, it really works. Think about how decisions flow in

26
00:01:16.920 --> 00:01:19.719
<v Speaker 2>the cemetery, the big strategic stuff that's handled way up

27
00:01:19.760 --> 00:01:22.480
<v Speaker 2>the chain. The soldier on the ground, that's our developer.

28
00:01:22.719 --> 00:01:25.680
<v Speaker 2>They operate on a strict need to know. They trust

29
00:01:25.680 --> 00:01:28.799
<v Speaker 2>their superiors. The library authors have handled the bigger picture,

30
00:01:28.840 --> 00:01:29.879
<v Speaker 2>the complex context.

31
00:01:30.000 --> 00:01:33.840
<v Speaker 1>You see that payoff immediately in software right like memory management.

32
00:01:33.480 --> 00:01:38.079
<v Speaker 2>Perfect example, Python's garbage collector handles memory. You the developer,

33
00:01:38.319 --> 00:01:41.239
<v Speaker 2>you don't spend any time thinking about deallocating things. You

34
00:01:41.359 --> 00:01:43.959
<v Speaker 2>just focus on solving the business problem at hand. It

35
00:01:44.040 --> 00:01:44.959
<v Speaker 2>speeds things.

36
00:01:44.799 --> 00:01:47.239
<v Speaker 1>Up, provided the abstraction holds up exactly.

37
00:01:47.719 --> 00:01:50.439
<v Speaker 2>But software, well, it's rarely perfect, is it so?

38
00:01:50.599 --> 00:01:54.040
<v Speaker 1>Okay? If the library author built this nice abstraction, why

39
00:01:54.040 --> 00:01:57.000
<v Speaker 1>should I, the end developer, be trying to poke holes

40
00:01:57.040 --> 00:01:58.400
<v Speaker 1>in it? Isn't that risky.

41
00:01:58.719 --> 00:02:00.400
<v Speaker 2>That's where the other side of the coin comes in,

42
00:02:00.439 --> 00:02:03.719
<v Speaker 2>the escape patch. Abstraction becomes a cage if you can't

43
00:02:03.760 --> 00:02:07.719
<v Speaker 2>get to functionality that wasn't exposed, or, more commonly, when

44
00:02:07.840 --> 00:02:10.280
<v Speaker 2>something breaks at runtime, you need to see what the

45
00:02:10.280 --> 00:02:13.719
<v Speaker 2>system is actually doing under the hood. Python's genius, i

46
00:02:13.719 --> 00:02:19.000
<v Speaker 2>think is providing some really excellent escape patches. It hides details, sure,

47
00:02:19.680 --> 00:02:21.800
<v Speaker 2>but it always lets you inspect the machinery if you

48
00:02:21.879 --> 00:02:22.159
<v Speaker 2>need to.

49
00:02:22.400 --> 00:02:26.879
<v Speaker 1>Okay, so that core philosophy need to know plus escape patch.

50
00:02:27.439 --> 00:02:31.199
<v Speaker 1>How does that translate into like everyday coding the conventions?

51
00:02:31.319 --> 00:02:33.719
<v Speaker 2>Right? It flows directly into things like readability. You know

52
00:02:33.759 --> 00:02:36.800
<v Speaker 2>that line from the Xeno Python readability.

53
00:02:36.199 --> 00:02:37.439
<v Speaker 1>Counts always a good reminder.

54
00:02:37.560 --> 00:02:40.280
<v Speaker 2>It's more than just nice to have, though for enterprise

55
00:02:40.319 --> 00:02:44.319
<v Speaker 2>code it's absolutely critical. Unreadable code means technical debt piles

56
00:02:44.400 --> 00:02:47.639
<v Speaker 2>up fast maintenance is a nightmare. Onboarding new people takes

57
00:02:47.680 --> 00:02:51.159
<v Speaker 2>forever because they're just guessing. Consistent standards are really the

58
00:02:51.199 --> 00:02:52.960
<v Speaker 2>foundation for software that lasts.

59
00:02:53.080 --> 00:02:56.120
<v Speaker 1>Let's get specific. Naming things always a fun one.

60
00:02:56.240 --> 00:03:00.000
<v Speaker 2>Oh yeah, Descriptive names are just non negotiable on Python.

61
00:03:00.080 --> 00:03:03.039
<v Speaker 2>On you have to remember Python uses dynamic typing, right

62
00:03:03.280 --> 00:03:07.000
<v Speaker 2>duct typing. You don't declare types like in Java or

63
00:03:07.080 --> 00:03:09.039
<v Speaker 2>C plus plus way, so the name you give a

64
00:03:09.159 --> 00:03:12.319
<v Speaker 2>variable is often the main clue, sometimes the only clue

65
00:03:12.319 --> 00:03:12.960
<v Speaker 2>about what it's for.

66
00:03:13.360 --> 00:03:15.639
<v Speaker 1>So using x isn't just lazy, it's actually kind of

67
00:03:15.680 --> 00:03:18.680
<v Speaker 1>dangerous because the language itself isn't giving you those type

68
00:03:18.800 --> 00:03:20.000
<v Speaker 1>clues precisely.

69
00:03:20.319 --> 00:03:24.319
<v Speaker 2>If you see yz, are those coordinates customer IDs who knows,

70
00:03:24.520 --> 00:03:27.840
<v Speaker 2>but first name, last name instantly clear, And here's a

71
00:03:27.879 --> 00:03:31.680
<v Speaker 2>warning from the source, watch out for abbreviations. Using dB

72
00:03:32.039 --> 00:03:35.199
<v Speaker 2>for double might seem fine until someone sees it near

73
00:03:35.280 --> 00:03:40.039
<v Speaker 2>database code and waste time assuming it means database avoid ambiguity.

74
00:03:40.280 --> 00:03:42.960
<v Speaker 1>That clarity extends to lay out too right. White space

75
00:03:43.000 --> 00:03:44.280
<v Speaker 1>actually matters in Python.

76
00:03:44.400 --> 00:03:47.639
<v Speaker 2>It absolutely does vertical white space especially it's about structure

77
00:03:47.800 --> 00:03:50.719
<v Speaker 2>and aesthetics. The guideline is two blank lines around top

78
00:03:50.800 --> 00:03:54.240
<v Speaker 2>level functions and classes that visually separates the big chunks.

79
00:03:54.000 --> 00:03:55.719
<v Speaker 1>Of functionality and within a class.

80
00:03:55.800 --> 00:03:58.599
<v Speaker 2>Inside a class, you use just one blank line around

81
00:03:58.599 --> 00:03:59.400
<v Speaker 2>method definitions.

82
00:03:59.680 --> 00:04:03.240
<v Speaker 1>Seems small, but looking at a big file, those gaps

83
00:04:03.319 --> 00:04:05.759
<v Speaker 1>must really help your eyes track the structure.

84
00:04:05.919 --> 00:04:08.800
<v Speaker 2>They really do. And even inside a function, you can

85
00:04:08.879 --> 00:04:12.360
<v Speaker 2>use blank lines maybe one to separate variable setup from

86
00:04:12.400 --> 00:04:14.840
<v Speaker 2>the main logic and then from their return statement. It

87
00:04:14.840 --> 00:04:17.240
<v Speaker 2>gives the code breathing room logical breaks.

88
00:04:17.399 --> 00:04:20.879
<v Speaker 1>Okay, documentation people often mix up comments and dock strings.

89
00:04:21.000 --> 00:04:21.759
<v Speaker 1>What's the difference.

90
00:04:21.839 --> 00:04:25.399
<v Speaker 2>Yeah, they serve totally different roles. Comments are well, they're

91
00:04:25.639 --> 00:04:28.399
<v Speaker 2>ignored by the Python interpreter. They are notes for humans.

92
00:04:28.600 --> 00:04:31.319
<v Speaker 2>Keep them short like seventy to eighty characters. And the

93
00:04:31.399 --> 00:04:35.160
<v Speaker 2>crucial thing the text really emphasizes this. If you write

94
00:04:35.199 --> 00:04:38.759
<v Speaker 2>a comment, you must keep it updated when the code changes.

95
00:04:39.079 --> 00:04:41.519
<v Speaker 1>The source called outdated comments landmines.

96
00:04:41.839 --> 00:04:46.279
<v Speaker 2>Why so harsh because they actively mislead. If there's no comment,

97
00:04:46.319 --> 00:04:48.439
<v Speaker 2>a developer knows they have to read the code carefully.

98
00:04:48.800 --> 00:04:51.759
<v Speaker 2>If there's an old comment that's wrong, they trust the comment,

99
00:04:51.920 --> 00:04:55.360
<v Speaker 2>follow bad advice and waste hours debugging something based on

100
00:04:55.399 --> 00:04:59.040
<v Speaker 2>a lie. For complex bits, use block comments explain properly.

101
00:04:59.120 --> 00:05:03.079
<v Speaker 2>And doc strings are different, totally different. Dock strings documentation

102
00:05:03.199 --> 00:05:07.759
<v Speaker 2>strings use triple quotes. Doc string goes here. The interpreter

103
00:05:07.839 --> 00:05:11.079
<v Speaker 2>does see these. You can access them programmatically using doc

104
00:05:11.319 --> 00:05:15.199
<v Speaker 2>They're meant for documenting the bigger pieces modules class as functions,

105
00:05:15.639 --> 00:05:18.959
<v Speaker 2>and importantly, tools like Sphinx can actually read these dock

106
00:05:19.040 --> 00:05:23.279
<v Speaker 2>strings and automatically generate proper documentation websites from your code.

107
00:05:23.560 --> 00:05:26.720
<v Speaker 1>Okay, and the third piece here is pipe hinting still

108
00:05:26.759 --> 00:05:30.839
<v Speaker 1>feels a bit newish in Python. You suggest types, but

109
00:05:30.879 --> 00:05:32.920
<v Speaker 1>Python itself doesn't check them at runtime.

110
00:05:33.000 --> 00:05:36.319
<v Speaker 2>That's the key point. Type hints or annotations are just

111
00:05:36.439 --> 00:05:39.040
<v Speaker 2>that hints. You can say a function expects a float,

112
00:05:39.279 --> 00:05:41.279
<v Speaker 2>Python won't complain. If you give it an end, it

113
00:05:41.360 --> 00:05:45.160
<v Speaker 2>runs fine. The value isn't runtime enforcement. It's clarity for

114
00:05:45.240 --> 00:05:48.639
<v Speaker 2>developers reading the code, and crucially it's for external tools.

115
00:05:49.399 --> 00:05:51.720
<v Speaker 2>If you want actual type checking, catching errors before you

116
00:05:51.800 --> 00:05:54.439
<v Speaker 2>run the code, you need a separate tool. Mypie is

117
00:05:54.480 --> 00:05:55.199
<v Speaker 2>the common one.

118
00:05:55.279 --> 00:05:58.160
<v Speaker 1>Ah, So my Pie acts like a static checker on

119
00:05:58.199 --> 00:06:00.639
<v Speaker 1>top of Python. It runs through your code, looks at

120
00:06:00.639 --> 00:06:03.439
<v Speaker 1>the hints, and flags potential type errors before they bite

121
00:06:03.439 --> 00:06:04.959
<v Speaker 1>you in production spot on.

122
00:06:05.519 --> 00:06:08.600
<v Speaker 2>It adds that layer of static analysis rigor, which is

123
00:06:08.600 --> 00:06:13.240
<v Speaker 2>great for larger projects, but without sacrificing Python's dynamic nature

124
00:06:13.399 --> 00:06:16.639
<v Speaker 2>during development. Best of both worlds, kind of right.

125
00:06:16.879 --> 00:06:19.879
<v Speaker 1>Let's circle back to those escape patches we said. Python

126
00:06:19.920 --> 00:06:23.079
<v Speaker 1>doesn't really do private members. You can basically poke around anywhere.

127
00:06:23.160 --> 00:06:26.600
<v Speaker 1>That freedom must enable some powerful techniques with data structures.

128
00:06:26.680 --> 00:06:29.639
<v Speaker 2>Oh absolutely, And the most Pythonic example has to be

129
00:06:30.000 --> 00:06:35.160
<v Speaker 2>list comprehensions. For simple loops transforming or filtering lists, they're

130
00:06:35.160 --> 00:06:39.040
<v Speaker 2>almost always preferred over map and filter. It's just so concise,

131
00:06:39.120 --> 00:06:39.720
<v Speaker 2>so readable.

132
00:06:39.839 --> 00:06:42.399
<v Speaker 1>But the source mentioned a performance boost too, something like

133
00:06:42.439 --> 00:06:45.279
<v Speaker 1>fifteen percent to thirty three percent faster. Why is that

134
00:06:45.360 --> 00:06:47.319
<v Speaker 1>It seems like just syntactic sugar.

135
00:06:47.600 --> 00:06:52.240
<v Speaker 2>It's deeper than sugar. It's about interpreter optimization. When Python

136
00:06:52.279 --> 00:06:55.000
<v Speaker 2>sees by two for x in my list, it can

137
00:06:55.079 --> 00:06:57.120
<v Speaker 2>often figure out or at least make a very good

138
00:06:57.160 --> 00:07:00.480
<v Speaker 2>guess about how big the final list will be. Allocates

139
00:07:00.480 --> 00:07:02.839
<v Speaker 2>the necessary memory for the whole new list right at

140
00:07:02.839 --> 00:07:03.240
<v Speaker 2>the start.

141
00:07:03.439 --> 00:07:05.279
<v Speaker 1>Ah, so it's not doing that thing where a list

142
00:07:05.319 --> 00:07:08.240
<v Speaker 1>grows hits capacity and has to reallocate a bigger chunk

143
00:07:08.279 --> 00:07:09.839
<v Speaker 1>of memory and copy everything over.

144
00:07:09.959 --> 00:07:13.680
<v Speaker 2>Exactly that Repeated resizing and copying in a standard for

145
00:07:13.879 --> 00:07:18.160
<v Speaker 2>loop using a pend is surprisingly expensive. List comprehensions often

146
00:07:18.240 --> 00:07:21.399
<v Speaker 2>sidestep that whole process, So yeah, use them for clarity,

147
00:07:21.560 --> 00:07:23.759
<v Speaker 2>but know you're likely getting a performance win too.

148
00:07:24.000 --> 00:07:28.240
<v Speaker 1>That's a great insight. Okay, what about checking items in sequences? Yeah,

149
00:07:28.279 --> 00:07:29.600
<v Speaker 1>all and any.

150
00:07:29.439 --> 00:07:31.920
<v Speaker 2>Yeah, super useful built ins. They check the truthiness of

151
00:07:32.000 --> 00:07:34.759
<v Speaker 2>items in an iterable All is like a logical A

152
00:07:35.480 --> 00:07:38.680
<v Speaker 2>and D are all items true? Any is a logical O,

153
00:07:39.000 --> 00:07:40.839
<v Speaker 2>R is at least one item true.

154
00:07:41.199 --> 00:07:43.680
<v Speaker 1>And they're efficient because they short circuit. How does that work?

155
00:07:44.120 --> 00:07:46.360
<v Speaker 2>Take all? As soon as it finds the first item

156
00:07:46.399 --> 00:07:48.920
<v Speaker 2>in your list that's false, like zero or an empty

157
00:07:48.959 --> 00:07:52.079
<v Speaker 2>string or none, it stops. It doesn't need to check

158
00:07:52.079 --> 00:07:54.639
<v Speaker 2>the rest it already knows the answer is false. Saves

159
00:07:54.680 --> 00:07:55.519
<v Speaker 2>potentially a lot of.

160
00:07:55.439 --> 00:07:58.240
<v Speaker 1>Looping, and any does the opposite. Stops at the first true.

161
00:07:58.040 --> 00:08:02.000
<v Speaker 2>Exactly finds one true thing, returns's true. Done very efficient.

162
00:08:01.680 --> 00:08:04.319
<v Speaker 1>And there's negative indexing. Simple but elegant.

163
00:08:04.639 --> 00:08:07.519
<v Speaker 2>It really is accessing from the end of a list

164
00:08:07.639 --> 00:08:10.800
<v Speaker 2>or string using negative numbers like my list one for

165
00:08:10.839 --> 00:08:13.720
<v Speaker 2>the last item or word dash two for the last

166
00:08:13.759 --> 00:08:17.639
<v Speaker 2>two letters. It just avoids needing to calculate lens sequence

167
00:08:17.720 --> 00:08:19.759
<v Speaker 2>one all the time. Cleaner code.

168
00:08:20.120 --> 00:08:23.120
<v Speaker 1>Okay. Finally, let's talk dictionaries. The source had this great

169
00:08:23.160 --> 00:08:26.600
<v Speaker 1>example of using them to replace switch case statements, which

170
00:08:26.720 --> 00:08:28.319
<v Speaker 1>Python famously lacks.

171
00:08:28.480 --> 00:08:31.839
<v Speaker 2>Yes, this is maybe the ultimate Pythonic escape patch for

172
00:08:31.959 --> 00:08:35.639
<v Speaker 2>control flow. Instead of a massive chain of if dot

173
00:08:35.679 --> 00:08:39.200
<v Speaker 2>ill if dot lf blocks to handle different commands or states,

174
00:08:39.840 --> 00:08:42.159
<v Speaker 2>you use a dictionary. You map the command string say

175
00:08:42.360 --> 00:08:45.240
<v Speaker 2>ad or multiply directly to the function that performs that action.

176
00:08:45.679 --> 00:08:48.080
<v Speaker 2>You can even store functions from the operator module like

177
00:08:48.120 --> 00:08:51.240
<v Speaker 2>operator dot ad as the dictionary values, then handling a

178
00:08:51.240 --> 00:08:53.879
<v Speaker 2>command becomes a simple dictionary lookup, and then calling the

179
00:08:53.919 --> 00:08:57.080
<v Speaker 2>function you found. It's incredibly clean and scales beautifully compared

180
00:08:57.120 --> 00:08:58.080
<v Speaker 2>to endless lves.

181
00:08:58.159 --> 00:09:00.600
<v Speaker 1>So wrapping this up, it sounds like Python's real strength

182
00:09:00.639 --> 00:09:02.080
<v Speaker 1>isn't just that it's simple to pick up.

183
00:09:02.320 --> 00:09:04.799
<v Speaker 2>No, not at all. It's that balance we talked about.

184
00:09:04.960 --> 00:09:07.879
<v Speaker 2>It uses conventions and abstractions, the need to know to

185
00:09:07.919 --> 00:09:11.559
<v Speaker 2>keep things focused, But crucially, when you hit the limits

186
00:09:11.559 --> 00:09:14.639
<v Speaker 2>of that abstraction or need raw performance, it gives you

187
00:09:14.679 --> 00:09:18.480
<v Speaker 2>powerful escape patches through direct access and clever use of

188
00:09:18.519 --> 00:09:19.440
<v Speaker 2>it's built in types.

189
00:09:19.600 --> 00:09:22.840
<v Speaker 1>An incredibly well balanced sense of what developers need, as

190
00:09:22.879 --> 00:09:25.480
<v Speaker 1>the source puts it, which brings us to our final

191
00:09:25.559 --> 00:09:28.679
<v Speaker 1>provocative thought for you, the listener. If you think you've

192
00:09:28.720 --> 00:09:31.720
<v Speaker 1>got Python figured out, try this expression, what do you

193
00:09:31.759 --> 00:09:33.840
<v Speaker 1>think this dictionary definition produces?

194
00:09:33.879 --> 00:09:34.200
<v Speaker 2>Ready?

195
00:09:34.320 --> 00:09:34.720
<v Speaker 1>It's two?

196
00:09:34.840 --> 00:09:35.080
<v Speaker 2>Yes?

197
00:09:35.279 --> 00:09:35.360
<v Speaker 1>What?

198
00:09:35.480 --> 00:09:35.639
<v Speaker 2>Hell?

199
00:09:35.679 --> 00:09:35.720
<v Speaker 1>No?

200
00:09:35.879 --> 00:09:37.000
<v Speaker 2>Open? Do you re sure?

201
00:09:37.080 --> 00:09:39.600
<v Speaker 1>Take a moment? What would you expect? Maybe all three

202
00:09:39.679 --> 00:09:42.039
<v Speaker 1>key value pairs? The actual result when you run that

203
00:09:42.200 --> 00:09:43.639
<v Speaker 1>is just true? Sure?

204
00:09:43.759 --> 00:09:45.440
<v Speaker 2>Okay, that is weird? What happened to one on one?

205
00:09:45.440 --> 00:09:45.679
<v Speaker 1>One? Oh?

206
00:09:45.799 --> 00:09:48.960
<v Speaker 2>Why only true? And why the value? Sure? This dives

207
00:09:49.039 --> 00:09:53.919
<v Speaker 2>right into Python's underlying mechanics. Fundamentally, Python treats the boolean

208
00:09:54.000 --> 00:09:57.679
<v Speaker 2>true as a kind of integer. Specifically, it's equal to one,

209
00:09:58.240 --> 00:10:02.200
<v Speaker 2>and when Python compares keys for dictionary, it checks for equality.

210
00:10:02.879 --> 00:10:05.639
<v Speaker 2>The expression true equals one is true, and one equals

211
00:10:05.720 --> 00:10:09.600
<v Speaker 2>one point zero is also true. So Python considers true, one,

212
00:10:09.639 --> 00:10:12.519
<v Speaker 2>and one point zero to be equivalent keys. As it

213
00:10:12.519 --> 00:10:15.320
<v Speaker 2>builds the dictionary, it sees true, assigns yes. Then it

214
00:10:15.320 --> 00:10:17.600
<v Speaker 2>sees one, which is equivalent, so it overwrites the value

215
00:10:17.639 --> 00:10:19.919
<v Speaker 2>for that key slot with hell No. Then it sees

216
00:10:20.000 --> 00:10:22.639
<v Speaker 2>one point zero, which is also equivalent, and overwrites the

217
00:10:22.679 --> 00:10:25.159
<v Speaker 2>value again with sure. You're left with the first key

218
00:10:25.399 --> 00:10:28.039
<v Speaker 2>true because it's hash comes first usually, and the last

219
00:10:28.080 --> 00:10:30.480
<v Speaker 2>value associated with any of those equivalent keys. It's a

220
00:10:30.559 --> 00:10:33.320
<v Speaker 2>neat little reminder of the details lurking beneath the surface.

221
00:10:33.200 --> 00:10:36.879
<v Speaker 1>A fantastic example of how even seemingly simple Python code

222
00:10:36.919 --> 00:10:39.759
<v Speaker 1>can have surprising depth. Always more to learn. Thank you

223
00:10:39.759 --> 00:10:41.080
<v Speaker 1>for digging into this with us today.

224
00:10:41.200 --> 00:10:42.840
<v Speaker 2>My pleasure always fun talking Python
