1
00:00:05,620 --> 00:00:07,520
Now as we saw in the previous videos

2
00:00:07,520 --> 00:00:08,650
in this section,

3
00:00:08,650 --> 00:00:11,380
Python classes don't need getters and setters

4
00:00:11,380 --> 00:00:13,280
to allow you to read and change the values

5
00:00:13,280 --> 00:00:15,030
of their data attributes

6
00:00:15,030 --> 00:00:17,680
or instance variables if you're more familiar with that term

7
00:00:17,680 --> 00:00:20,040
from other programming languages.

8
00:00:20,040 --> 00:00:21,490
Python adopts the philosophy

9
00:00:21,490 --> 00:00:23,570
that we're all responsible adults

10
00:00:23,570 --> 00:00:25,420
so it doesn't have the facility

11
00:00:25,420 --> 00:00:27,800
to make class attributes private

12
00:00:27,800 --> 00:00:30,660
like many other object oriented languages do.

13
00:00:30,660 --> 00:00:31,550
Now with that said,

14
00:00:31,550 --> 00:00:34,090
getters and setters are still useful in Python,

15
00:00:34,090 --> 00:00:36,630
even if they're not essential so in this video,

16
00:00:36,630 --> 00:00:38,440
we're gonna take a look at what they are,

17
00:00:38,440 --> 00:00:41,500
how to create them, and why you might want to do so.

18
00:00:41,500 --> 00:00:42,780
Now I'm gonna start off

19
00:00:42,780 --> 00:00:45,430
by doing something quite controversial.

20
00:00:45,430 --> 00:00:49,350
I'm gonna put each of our classes in a separate file.

21
00:00:49,350 --> 00:00:53,250
Now this is the usual way of doing things in C++ or Java,

22
00:00:53,250 --> 00:00:56,570
but there's no need to have one file per class in Python.

23
00:00:56,570 --> 00:00:57,400
And in fact,

24
00:00:57,400 --> 00:00:59,780
if I was creating these classes in a working programme,

25
00:00:59,780 --> 00:01:02,970
I would actually keep them all in the same file.

26
00:01:02,970 --> 00:01:04,560
But the reason I'm gonna do that here

27
00:01:04,560 --> 00:01:06,830
is because we're gonna be flicking back and forth

28
00:01:06,830 --> 00:01:08,600
looking at the various classes

29
00:01:08,600 --> 00:01:10,450
while I describe what's going on

30
00:01:10,450 --> 00:01:12,170
and that's much easier to do

31
00:01:12,170 --> 00:01:14,680
if each class appears in its own tab in the editor

32
00:01:14,680 --> 00:01:17,400
rather than scrolling up and down through a single file.

33
00:01:17,400 --> 00:01:20,020
And it also provides an excuse to show you another way

34
00:01:20,020 --> 00:01:21,650
of importing a class.

35
00:01:21,650 --> 00:01:22,480
So I'm doing it here

36
00:01:22,480 --> 00:01:25,480
but remember that it's not necessary to do this in Python.

37
00:01:25,480 --> 00:01:28,300
You're better off keeping related classes in the same file

38
00:01:28,300 --> 00:01:31,850
so that each file is organised based on functionality.

39
00:01:31,850 --> 00:01:33,600
Okay, so we're gonna use the characters

40
00:01:33,600 --> 00:01:36,210
in a role playing type game for our examples

41
00:01:36,210 --> 00:01:38,280
so let's create a new Python project.

42
00:01:38,280 --> 00:01:40,750
We're gonna call it game.

43
00:01:40,750 --> 00:01:42,830
Python is selected there.

44
00:01:43,720 --> 00:01:44,550
Game.

45
00:01:48,840 --> 00:01:50,450
Now our first class is gonna be used

46
00:01:50,450 --> 00:01:52,820
to represent the people playing the game

47
00:01:52,820 --> 00:01:56,760
so let's create a new Python file called player.py

48
00:01:56,760 --> 00:01:58,860
so I'm just gonna come over here as normal,

49
00:01:58,860 --> 00:02:02,720
right click, new, Python file, file I should say,

50
00:02:02,720 --> 00:02:05,220
player is the name, all right.

51
00:02:07,580 --> 00:02:09,580
So each player is gonna have a name

52
00:02:09,580 --> 00:02:12,130
as well as things like the number of lives they've got left

53
00:02:12,130 --> 00:02:13,400
and their score.

54
00:02:13,400 --> 00:02:16,160
So we're gonna start with this basic player class.

55
00:02:16,160 --> 00:02:20,330
So we're gonna type class Player object colon enter enter

56
00:02:23,640 --> 00:02:27,800
and then we're gonna do def space underscore underscore init

57
00:02:28,840 --> 00:02:31,800
and you saw that I just selected that for ourself,

58
00:02:31,800 --> 00:02:34,640
but then I also need to do a semicolon and a name

59
00:02:34,640 --> 00:02:38,810
for the parameter and we're gonna do self.name equals name

60
00:02:41,230 --> 00:02:45,090
then we're gonna do self.lives is equal to three,

61
00:02:45,090 --> 00:02:49,260
self.level is equal to one and self.score equals zero.

62
00:02:52,770 --> 00:02:54,440
So the convention is that class name

63
00:02:54,440 --> 00:02:56,160
should start with a capital letter,

64
00:02:56,160 --> 00:02:58,340
although some of the built-in classes in Python

65
00:02:58,340 --> 00:03:00,180
don't follow that convention.

66
00:03:00,180 --> 00:03:03,290
Now this is a very simple class with four data attributes

67
00:03:03,290 --> 00:03:05,930
and their given values in the class constructor,

68
00:03:05,930 --> 00:03:07,440
the underscore underscore init,

69
00:03:07,440 --> 00:03:09,290
underscore underscore method.

70
00:03:09,290 --> 00:03:11,430
And again, that's the class constructor.

71
00:03:11,430 --> 00:03:13,770
Now we pass one of these values as a parameter

72
00:03:13,770 --> 00:03:15,500
so when we create each player,

73
00:03:15,500 --> 00:03:18,070
they're given a name when they're created.

74
00:03:18,070 --> 00:03:20,790
Now the other three values start off with default values,

75
00:03:20,790 --> 00:03:24,650
three for lives, one for level and a score of zero.

76
00:03:24,650 --> 00:03:26,240
All right, so we're going to put all the code

77
00:03:26,240 --> 00:03:29,390
that uses the classes in a file called main.py

78
00:03:29,390 --> 00:03:32,640
so let's go ahead and create that.

79
00:03:32,640 --> 00:03:36,810
We're gonna right click on new Python file, call it main,

80
00:03:39,870 --> 00:03:43,620
and the code is gonna be import space Player,

81
00:03:45,610 --> 00:03:49,780
tim equals player in lowercase dot player in uppercase

82
00:03:52,880 --> 00:03:53,960
and then tim,

83
00:03:55,750 --> 00:03:58,660
print tim.name and print tim.lives.

84
00:04:04,220 --> 00:04:06,560
Okay, now I've accidentally put a capital P in there

85
00:04:06,560 --> 00:04:09,540
for the import and it should've been lowercase P

86
00:04:09,540 --> 00:04:11,710
because the filename you can see in the top left hand corner

87
00:04:11,710 --> 00:04:14,450
has a lowercase P for the name

88
00:04:14,450 --> 00:04:16,640
so I'll just do a lowercase P

89
00:04:16,640 --> 00:04:19,260
and we can see it's now finding it

90
00:04:19,260 --> 00:04:21,570
and that error should disappear.

91
00:04:21,570 --> 00:04:25,540
All right, so just to confirm this, if we run this now,

92
00:04:25,540 --> 00:04:27,460
okay, we can see there,

93
00:04:28,390 --> 00:04:29,840
I'm gonna move this down to the bottom,

94
00:04:29,840 --> 00:04:34,460
the player's name is tim and he's got three lives.

95
00:04:34,460 --> 00:04:36,570
All right, now having to type player with lowercase

96
00:04:36,570 --> 00:04:38,470
dot player in uppercase

97
00:04:38,470 --> 00:04:40,370
every time we wanna refer to the player class

98
00:04:40,370 --> 00:04:41,810
is gonna be a bit annoying

99
00:04:41,810 --> 00:04:45,520
so we can change the way that we input the player module

100
00:04:45,520 --> 00:04:46,820
to avoid this.

101
00:04:46,820 --> 00:04:49,320
So up here on line one, let's actually change this

102
00:04:49,320 --> 00:04:50,280
instead of import player to be

103
00:04:50,280 --> 00:04:53,780
from player import Player with a capital P

104
00:04:58,630 --> 00:05:00,440
and then we can just change this definition here

105
00:05:00,440 --> 00:05:03,100
just to be tim equals Player tim

106
00:05:04,160 --> 00:05:07,850
and we can run this and we get the same result.

107
00:05:07,850 --> 00:05:10,980
So basically we can refer to the player class

108
00:05:10,980 --> 00:05:13,560
without having to qualify it with the module name.

109
00:05:13,560 --> 00:05:15,900
Now I did suggest previously

110
00:05:15,900 --> 00:05:18,050
that you don't use this kind of import

111
00:05:18,050 --> 00:05:20,400
and generally I wouldn't recommend it.

112
00:05:20,400 --> 00:05:21,460
But here though,

113
00:05:21,460 --> 00:05:24,450
each module is only gonna contain a single class

114
00:05:24,450 --> 00:05:26,650
so there's really not gonna be any confusion

115
00:05:26,650 --> 00:05:28,750
about where a player is coming from.

116
00:05:28,750 --> 00:05:29,580
Now as I've said,

117
00:05:29,580 --> 00:05:32,320
you probably wouldn't place each class in its own file,

118
00:05:32,320 --> 00:05:34,880
but as we are doing that to this exercise,

119
00:05:34,880 --> 00:05:38,060
we may as well make it a lot easier for ourselves.

120
00:05:38,060 --> 00:05:41,410
All right, so we've got a basic player class

121
00:05:41,410 --> 00:05:43,640
and we could take lives away from the players

122
00:05:43,640 --> 00:05:45,350
as we get into scraps and take damage

123
00:05:45,350 --> 00:05:47,740
from the monsters that they'll be fighting.

124
00:05:47,740 --> 00:05:51,120
So we can do something like here on line seven

125
00:05:51,120 --> 00:05:53,280
tim.lives minus equals one

126
00:05:55,320 --> 00:05:58,100
which is obviously going to deduct the number of lives,

127
00:05:58,100 --> 00:05:59,810
one from the number of lives,

128
00:05:59,810 --> 00:06:04,240
and print out tim.lives and if you run this,

129
00:06:04,240 --> 00:06:06,280
we get this at the bottom of the screen

130
00:06:06,280 --> 00:06:10,310
showing the lives has been decremented and it's now two.

131
00:06:10,310 --> 00:06:12,000
So this is making fine

132
00:06:12,000 --> 00:06:13,980
and the code is accessing the player class

133
00:06:13,980 --> 00:06:17,080
data attributes directly to print them out

134
00:06:17,080 --> 00:06:18,840
or alter their values.

135
00:06:18,840 --> 00:06:22,100
Now the attributes such as lives and names

136
00:06:22,100 --> 00:06:24,700
are encapsulated in the player class,

137
00:06:24,700 --> 00:06:26,180
but they're not hidden

138
00:06:26,180 --> 00:06:30,460
and that's something that I'm sure Java and C++ programmers

139
00:06:30,460 --> 00:06:33,540
will find horrible because in those languages,

140
00:06:33,540 --> 00:06:35,910
providing direct access to the data attributes

141
00:06:35,910 --> 00:06:38,710
is really frowned upon but in Python,

142
00:06:38,710 --> 00:06:40,130
it's considered the opposite,

143
00:06:40,130 --> 00:06:42,670
in other words the way to do things.

144
00:06:42,670 --> 00:06:45,140
So the first thing I'm gonna say about getters and setters

145
00:06:45,140 --> 00:06:48,150
in Python is don't use them.

146
00:06:48,150 --> 00:06:50,220
And I guess that's probably a strange thing to say

147
00:06:50,220 --> 00:06:53,250
in a video about using getters and setters in Python

148
00:06:53,250 --> 00:06:56,200
so I better explain that I don't mean never use them,

149
00:06:56,200 --> 00:06:58,070
I mean don't worry about them

150
00:06:58,070 --> 00:07:00,170
when you're creating your classes

151
00:07:00,170 --> 00:07:02,800
and that's because chances are you won't need them

152
00:07:02,800 --> 00:07:05,500
so don't spend time creating getters and setters

153
00:07:05,500 --> 00:07:08,000
that won't be needed.

154
00:07:08,000 --> 00:07:12,830
Now in Python, you can add a getter or a setter or both

155
00:07:12,830 --> 00:07:16,480
after you created your class and any code using the class

156
00:07:16,480 --> 00:07:18,440
will continue to work fine,

157
00:07:18,440 --> 00:07:21,720
but in Java or C++ that's not possible.

158
00:07:21,720 --> 00:07:25,470
If you allow access to class instance variables later

159
00:07:25,470 --> 00:07:27,210
to start to make them private,

160
00:07:27,210 --> 00:07:30,090
any code that uses the class will have to be changed

161
00:07:30,090 --> 00:07:32,640
to use the getters and setters instead.

162
00:07:32,640 --> 00:07:35,090
As we see in Python though, client code,

163
00:07:35,090 --> 00:07:38,710
that's code that is using the class, isn't affected.

164
00:07:38,710 --> 00:07:41,420
All right, so what are these getters and setters?

165
00:07:41,420 --> 00:07:43,290
Well, a getter is actually a method

166
00:07:43,290 --> 00:07:47,270
that's used to get the value of a data attribute.

167
00:07:47,270 --> 00:07:50,580
So as an example, if we look at the code on line five,

168
00:07:50,580 --> 00:07:52,070
it's actually printing out

169
00:07:52,070 --> 00:07:55,320
the data attribute directly, tim.name,

170
00:07:55,320 --> 00:07:57,160
so instead of that if we wanted to access a name,

171
00:07:57,160 --> 00:07:59,480
we might come down and do something like this,

172
00:07:59,480 --> 00:08:02,650
print tim.get underscore name like so.

173
00:08:07,280 --> 00:08:10,970
So the get underscore name method is called a getter

174
00:08:10,970 --> 00:08:12,740
and normally it just returns the value

175
00:08:12,740 --> 00:08:14,810
of the corresponding variable,

176
00:08:14,810 --> 00:08:16,480
but it can actually do more than that.

177
00:08:16,480 --> 00:08:18,490
For example, the getter for the score

178
00:08:18,490 --> 00:08:21,620
could multiply the score by perhaps the number of lives.

179
00:08:21,620 --> 00:08:23,930
That way, a player's score is much higher

180
00:08:23,930 --> 00:08:27,180
if they've completed the game without losing too many lives.

181
00:08:27,180 --> 00:08:28,850
So getters can be useful

182
00:08:28,850 --> 00:08:30,950
and you'll want to add them sometimes,

183
00:08:30,950 --> 00:08:31,970
but the point I'm making

184
00:08:31,970 --> 00:08:33,510
is that you can add them to the class

185
00:08:33,510 --> 00:08:35,320
if you later decide you need them,

186
00:08:35,320 --> 00:08:36,940
but there's no point in creating them

187
00:08:36,940 --> 00:08:38,330
just for the sake of it

188
00:08:38,330 --> 00:08:41,320
or just because you've come to Python from another language

189
00:08:41,320 --> 00:08:42,860
where you have to use a getter

190
00:08:42,860 --> 00:08:45,390
if you think there might be the faintest possibility

191
00:08:45,390 --> 00:08:47,400
that you'll need one in the future.

192
00:08:47,400 --> 00:08:49,090
All right, so that's the getter,

193
00:08:49,090 --> 00:08:50,810
but a setter is just a method

194
00:08:50,810 --> 00:08:53,650
that's used to set the value of the class data attribute

195
00:08:53,650 --> 00:08:55,560
and it might look something like this,

196
00:08:55,560 --> 00:08:57,970
tim.set underscore lives 300.

197
00:09:01,340 --> 00:09:03,930
A setter may be useful for the lives attribute

198
00:09:03,930 --> 00:09:05,700
of our player class.

199
00:09:05,700 --> 00:09:07,680
It doesn't make sense for the number of lives

200
00:09:07,680 --> 00:09:11,130
to drop below zero so using a setter is a good way

201
00:09:11,130 --> 00:09:14,450
to check the value before updating the attribute.

202
00:09:14,450 --> 00:09:17,800
Now these two examples on line 10 and 11

203
00:09:17,800 --> 00:09:20,880
are how you would use a getter and setter in Java

204
00:09:20,880 --> 00:09:23,660
or C++ for example but in Python,

205
00:09:23,660 --> 00:09:26,380
they actually work a bit differently.

206
00:09:26,380 --> 00:09:28,380
Now the basic principle is the same,

207
00:09:28,380 --> 00:09:32,280
that is to use a method to return the value of an attribute

208
00:09:32,280 --> 00:09:33,990
or assign a new value to it,

209
00:09:33,990 --> 00:09:35,980
but you still use the same syntax

210
00:09:35,980 --> 00:09:39,540
as you would when accessing the attributes directly.

211
00:09:39,540 --> 00:09:42,290
I'm gonna delete these two lines.

212
00:09:45,640 --> 00:09:47,970
Let's go ahead and add a getter and setter

213
00:09:47,970 --> 00:09:50,930
for our lives attribute in the player class.

214
00:09:50,930 --> 00:09:53,650
All right, so going back to the player.py file,

215
00:09:53,650 --> 00:09:57,310
so the first thing we wanna do is hide our lives attribute

216
00:09:57,310 --> 00:09:59,980
by prefixing it with an underscore.

217
00:09:59,980 --> 00:10:02,190
I'm talking about the code here on line five.

218
00:10:02,190 --> 00:10:06,690
So it's gonna be self. and put an underscore there

219
00:10:06,690 --> 00:10:09,260
for underscore lives equals three.

220
00:10:09,260 --> 00:10:10,720
So once we've done that,

221
00:10:10,720 --> 00:10:14,160
we need to create a method to set the value to setter

222
00:10:14,160 --> 00:10:16,990
and of course another method to get the value to getter.

223
00:10:16,990 --> 00:10:19,690
Let's go ahead and do both of those.

224
00:10:19,690 --> 00:10:21,520
So we'll start with the getter

225
00:10:21,520 --> 00:10:25,690
so that's gonna be def space underscore get underscore lives

226
00:10:27,920 --> 00:10:31,670
self colon and return self. underscore lives.

227
00:10:35,560 --> 00:10:40,390
Then we'll do a def underscore set underscore lives

228
00:10:40,390 --> 00:10:41,680
and self in parenthesis

229
00:10:41,680 --> 00:10:43,770
which is added automatically by IntelliJ

230
00:10:43,770 --> 00:10:47,480
and then we're gonna do self. underscore lives

231
00:10:47,480 --> 00:10:48,980
is equal to lives.

232
00:10:50,540 --> 00:10:52,690
And the other thing I'll need to do here is add a parameter

233
00:10:52,690 --> 00:10:54,110
because it's the set method.

234
00:10:54,110 --> 00:10:57,010
We need to pass the number of lives we wanna set it to

235
00:10:57,010 --> 00:10:57,960
and that's it.

236
00:10:57,960 --> 00:10:59,830
Now once again, we're hiding these methods

237
00:10:59,830 --> 00:11:02,580
by starting their names with an underscore.

238
00:11:02,580 --> 00:11:04,930
Of course, they're not really hidden as such,

239
00:11:04,930 --> 00:11:07,480
but there's no need for clients to use them directly

240
00:11:07,480 --> 00:11:09,810
and the underscore at the start of the name

241
00:11:09,810 --> 00:11:12,540
gives users of our class an indication

242
00:11:12,540 --> 00:11:15,960
that they shouldn't really be calling these methods.

243
00:11:15,960 --> 00:11:17,870
Okay, so the last step now

244
00:11:17,870 --> 00:11:20,350
is to define a property called lives

245
00:11:20,350 --> 00:11:22,130
that uses these two methods

246
00:11:22,130 --> 00:11:25,240
when reading and writing our lives attribute.

247
00:11:25,240 --> 00:11:27,280
All right, so let's actually add that now.

248
00:11:27,280 --> 00:11:30,280
So we put lives is equal to property

249
00:11:32,760 --> 00:11:36,390
and it's going to be underscore get underscore lives

250
00:11:36,390 --> 00:11:37,890
without the parenthesis

251
00:11:37,890 --> 00:11:40,580
and underscore set underscore lives

252
00:11:40,580 --> 00:11:43,150
again without any parenthesis.

253
00:11:43,150 --> 00:11:46,440
So our data attribute is now called underscore lives

254
00:11:46,440 --> 00:11:49,590
and we've replaced it with a property called lives

255
00:11:49,590 --> 00:11:53,480
that uses these two methods to access the number of lives

256
00:11:53,480 --> 00:11:55,180
that the player has.

257
00:11:55,180 --> 00:11:58,810
Now back in main.py, if I go back over there,

258
00:11:58,810 --> 00:12:00,310
I can run the programme as is

259
00:12:00,310 --> 00:12:02,860
and everything should still work.

260
00:12:02,860 --> 00:12:05,280
We get the same results as we got previously.

261
00:12:05,280 --> 00:12:07,210
Tim starts off with three lives

262
00:12:07,210 --> 00:12:09,890
which we've printed out on line six.

263
00:12:09,890 --> 00:12:13,430
Then there's two left after we subtract one on line seven

264
00:12:13,430 --> 00:12:15,170
and obviously we're printing out the results of that

265
00:12:15,170 --> 00:12:16,510
on line eight.

266
00:12:16,510 --> 00:12:19,040
So I haven't actually had to make any changes

267
00:12:19,040 --> 00:12:20,610
to our main programme

268
00:12:20,610 --> 00:12:23,120
so it continues to use the player class

269
00:12:23,120 --> 00:12:24,890
in exactly the same way as it did

270
00:12:24,890 --> 00:12:27,420
before we changed the lives attribute

271
00:12:27,420 --> 00:12:29,720
to use the getter and setter methods.

272
00:12:29,720 --> 00:12:30,820
But now that we've done this,

273
00:12:30,820 --> 00:12:33,560
we can add some validation to the setter method

274
00:12:33,560 --> 00:12:36,940
to prevent the number of lives from dropping below zero.

275
00:12:36,940 --> 00:12:40,500
So going back to our player class in the setter method,

276
00:12:40,500 --> 00:12:44,410
we could add some code to do that validation

277
00:12:44,410 --> 00:12:47,450
so we could put if space lives

278
00:12:47,450 --> 00:12:50,780
is greater than or equal to zero colon

279
00:12:50,780 --> 00:12:55,300
then we'll put our self. underscore lives equals lives

280
00:12:55,300 --> 00:12:57,820
then we'll add an else clause else

281
00:12:57,820 --> 00:13:01,820
and we've got our print lives cannot be negative

282
00:13:04,490 --> 00:13:08,100
and self. underscore lives equals zero.

283
00:13:08,100 --> 00:13:09,700
All right, so that's the validation

284
00:13:09,700 --> 00:13:11,000
that only effectively allows us

285
00:13:11,000 --> 00:13:13,610
to set the value of the lives variable,

286
00:13:13,610 --> 00:13:15,120
underscore lives variable,

287
00:13:15,120 --> 00:13:18,560
if the values passed is greater than or equal to zero.

288
00:13:18,560 --> 00:13:20,080
And if that's not the case,

289
00:13:20,080 --> 00:13:22,930
then we print out the message lives cannot be negative

290
00:13:22,930 --> 00:13:25,430
and then we set underscore lives to zero.

291
00:13:25,430 --> 00:13:26,830
So while I'm here,

292
00:13:26,830 --> 00:13:28,220
I'm gonna add a method that we can use

293
00:13:28,220 --> 00:13:30,250
to print out the values of the attributes

294
00:13:30,250 --> 00:13:31,270
so let's go ahead and do that.

295
00:13:31,270 --> 00:13:35,150
We'll put that below the lives property line.

296
00:13:35,150 --> 00:13:39,320
We def space underscore underscore str underscore underscore

297
00:13:42,290 --> 00:13:45,080
and we add the self which added automatically by IntelliJ

298
00:13:45,080 --> 00:13:46,500
then let's return

299
00:13:47,600 --> 00:13:50,100
name and curly brace zero.name

300
00:13:53,460 --> 00:13:54,790
lives zero.lives

301
00:13:59,630 --> 00:14:00,970
level zero.level

302
00:14:05,200 --> 00:14:07,540
and finally score zero.score

303
00:14:10,060 --> 00:14:12,940
and at the end of that line after the double quote,

304
00:14:12,940 --> 00:14:14,020
.format self.

305
00:14:15,630 --> 00:14:16,890
So when you print an object,

306
00:14:16,890 --> 00:14:18,740
Python looks for a special method

307
00:14:18,740 --> 00:14:22,240
called underscore underscore str underscore underscore

308
00:14:22,240 --> 00:14:24,410
which we've just defined on line 21

309
00:14:24,410 --> 00:14:25,520
and I'm gonna call that method

310
00:14:25,520 --> 00:14:28,460
when it needs a string representation of the object

311
00:14:28,460 --> 00:14:30,750
such as when you wanna print it.

312
00:14:30,750 --> 00:14:32,280
Now I've created this method

313
00:14:32,280 --> 00:14:35,130
so that we can easily see the values of the attributes

314
00:14:35,130 --> 00:14:36,800
and I'll come back to that strange use

315
00:14:36,800 --> 00:14:39,300
of the replacement field shortly.

316
00:14:39,300 --> 00:14:42,020
Okay, so we've added some code to the lives setter

317
00:14:42,020 --> 00:14:44,160
to prevent the number of lives going negative

318
00:14:44,160 --> 00:14:45,470
so let's test this.

319
00:14:45,470 --> 00:14:48,280
So we're going back to the main programme

320
00:14:48,280 --> 00:14:52,650
and let's copy lines seven and eight three more times

321
00:14:52,650 --> 00:14:54,850
so I'm gonna copy those

322
00:14:54,850 --> 00:14:58,890
and let's put them outside there, there and three

323
00:14:58,890 --> 00:15:00,200
as you can see.

324
00:15:00,200 --> 00:15:02,590
So we're reducing the value of lives by one each time

325
00:15:02,590 --> 00:15:03,930
and printing out the value

326
00:15:03,930 --> 00:15:05,850
until we get down to the last value

327
00:15:05,850 --> 00:15:08,130
which hopefully is going to be hitting zero,

328
00:15:08,130 --> 00:15:09,250
but the other thing I probably should have done

329
00:15:09,250 --> 00:15:11,170
before I copied it was change this

330
00:15:11,170 --> 00:15:13,110
so instead of just printing out lives,

331
00:15:13,110 --> 00:15:15,550
it prints out just tim.

332
00:15:15,550 --> 00:15:16,430
And now that we've created

333
00:15:16,430 --> 00:15:19,200
that underscore underscore str function,

334
00:15:19,200 --> 00:15:23,480
let's take advantage of that, okay, like so.

335
00:15:23,480 --> 00:15:27,000
So let's run this now and see if it works.

336
00:15:27,000 --> 00:15:27,880
All right, so you can see there

337
00:15:27,880 --> 00:15:31,620
that we've got our lives getting reduced each time we call

338
00:15:31,620 --> 00:15:33,370
and then once it gets to below zero

339
00:15:33,370 --> 00:15:34,860
or would have gone below zero,

340
00:15:34,860 --> 00:15:37,480
we see that we got a message lives cannot be negative

341
00:15:37,480 --> 00:15:40,780
and the number of lives remains at zero.

342
00:15:40,780 --> 00:15:43,580
So although setters aren't needed as such in Python,

343
00:15:43,580 --> 00:15:46,430
they're very useful when you'd want to include validation

344
00:15:46,430 --> 00:15:50,380
on the values that your data attributes can be set to.

345
00:15:50,380 --> 00:15:52,060
All right, so I've skimmed over a couple of things

346
00:15:52,060 --> 00:15:54,700
that we've done in the player class so in the next video,

347
00:15:54,700 --> 00:15:57,100
let's have a look at those things in a bit more detail.

348
00:15:57,100 --> 00:15:59,280
I'll see you in the next video.

