1 00:00:00,000 --> 00:00:02,365 [MUSIC PLAYING] 2 00:00:02,365 --> 00:00:05,665 3 00:00:05,665 --> 00:00:07,540 SPEAKER: Well, hello one and all, and welcome 4 00:00:07,540 --> 00:00:10,270 to our short on the random module. 5 00:00:10,270 --> 00:00:12,520 Now the random module is a module you can 6 00:00:12,520 --> 00:00:16,400 use to add an element of randomness or chance to your programs. 7 00:00:16,400 --> 00:00:19,120 And we'll see here, I have a program called cards.py, 8 00:00:19,120 --> 00:00:22,600 which I've created by typing code cards.py, and adding 9 00:00:22,600 --> 00:00:27,200 in these lines of code on lines 1, 3, 4, and 7 down here. 10 00:00:27,200 --> 00:00:32,290 So the goal of cards.py is to simulate kind of dealing from this deck of cards 11 00:00:32,290 --> 00:00:35,230 that I have here in the form of this list, one 12 00:00:35,230 --> 00:00:39,530 called cards with three cards, jack, queen, and king. 13 00:00:39,530 --> 00:00:44,020 But if I want to deal cards, I could think of this element of randomness, 14 00:00:44,020 --> 00:00:47,360 shuffling the cards, and dealing them, and seeing what cards I get. 15 00:00:47,360 --> 00:00:51,170 And to get somewhat of randomness, we'll need to use the random module. 16 00:00:51,170 --> 00:00:55,396 So I can import it up top using import. 17 00:00:55,396 --> 00:00:57,470 Import random, just like this. 18 00:00:57,470 --> 00:00:59,590 And then down below, I can see a few ways 19 00:00:59,590 --> 00:01:03,860 to use the random module with a few functions that are built into it. 20 00:01:03,860 --> 00:01:08,360 Now one we've seen is the choice function, which I can get access to 21 00:01:08,360 --> 00:01:11,570 by calling random.choice. 22 00:01:11,570 --> 00:01:17,150 And .choice here, this function, takes as input some list and returns to me 23 00:01:17,150 --> 00:01:19,680 some random element from that list. 24 00:01:19,680 --> 00:01:24,350 So I think I could give as input here cards, my list, my deck of cards here, 25 00:01:24,350 --> 00:01:28,380 and have it choose for me one card randomly from this deck of three. 26 00:01:28,380 --> 00:01:31,260 I could then print the result just like this. 27 00:01:31,260 --> 00:01:35,100 If I go down below and type Python of cards.py, 28 00:01:35,100 --> 00:01:38,180 we'll see I got back queen from random.choice. 29 00:01:38,180 --> 00:01:41,480 Just to prove this is a bit random here, I'll do Python of cards.py, 30 00:01:41,480 --> 00:01:43,573 and I get queen again by chance. 31 00:01:43,573 --> 00:01:44,490 But let's keep trying. 32 00:01:44,490 --> 00:01:46,560 I'll get queen again. 33 00:01:46,560 --> 00:01:49,230 I'll do Python of cards.py, and there we go. 34 00:01:49,230 --> 00:01:53,810 Now we have a new card again, each one being chosen randomly by chance. 35 00:01:53,810 --> 00:01:57,570 So what else is built into the random module? 36 00:01:57,570 --> 00:02:00,650 Well, one that can be useful to you, one function, 37 00:02:00,650 --> 00:02:04,700 is not just choice, but choices, plural. 38 00:02:04,700 --> 00:02:09,800 And choices, true to its name, lets you choose not just one item from a list, 39 00:02:09,800 --> 00:02:11,670 but multiple if you wanted to. 40 00:02:11,670 --> 00:02:12,720 So let's try that out. 41 00:02:12,720 --> 00:02:16,040 I'll go down below and I'll type random.choices. 42 00:02:16,040 --> 00:02:18,200 And it turns out, if I read the documentation, 43 00:02:18,200 --> 00:02:21,050 I'll find out that choices, this function, 44 00:02:21,050 --> 00:02:26,670 takes as input its first argument the same list of options to choose from. 45 00:02:26,670 --> 00:02:30,950 And the second argument is one called k, which 46 00:02:30,950 --> 00:02:36,120 stands in for number of items I want to randomly choose from this list. 47 00:02:36,120 --> 00:02:39,840 So here, let's try choosing two cards instead of just one. 48 00:02:39,840 --> 00:02:41,910 I'll set k equal to 2. 49 00:02:41,910 --> 00:02:46,310 And now if I go down below and run Python of cards.py, 50 00:02:46,310 --> 00:02:47,840 let's see what we get. 51 00:02:47,840 --> 00:02:49,650 I'll get queen and king. 52 00:02:49,650 --> 00:02:52,730 So it seems like it randomly chose two cards from this deck 53 00:02:52,730 --> 00:02:55,432 and got back queen and king. 54 00:02:55,432 --> 00:02:56,640 Let's keep trying this again. 55 00:02:56,640 --> 00:03:00,380 I'll do python of cards.py, I'll get queen and jack. 56 00:03:00,380 --> 00:03:03,260 Python of cards.py, king and jack. 57 00:03:03,260 --> 00:03:07,720 And we can keep going here, but-- 58 00:03:07,720 --> 00:03:11,590 so here, I seem to have gotten queen and queen, which 59 00:03:11,590 --> 00:03:14,120 might not be what you'd expect. 60 00:03:14,120 --> 00:03:17,500 Now it turns out that random.choices is doing what's 61 00:03:17,500 --> 00:03:20,270 called sampling with replacement. 62 00:03:20,270 --> 00:03:25,360 It's akin to me having a deck of three, shuffling it, taking one card out, 63 00:03:25,360 --> 00:03:29,050 writing down that card, putting it back in, shuffling again, 64 00:03:29,050 --> 00:03:32,810 and choosing another random card from that same deck of three. 65 00:03:32,810 --> 00:03:37,210 So every time I choose a new card in this case, 66 00:03:37,210 --> 00:03:39,460 I'm choosing from this set of three. 67 00:03:39,460 --> 00:03:41,590 When I choose a card, that doesn't eliminate it 68 00:03:41,590 --> 00:03:46,040 from future choosing of my random choosing in this particular case. 69 00:03:46,040 --> 00:03:48,280 So this is sampling without-- 70 00:03:48,280 --> 00:03:50,590 or sampling with replacement. 71 00:03:50,590 --> 00:03:53,570 Adding the card, let's say, back into the deck. 72 00:03:53,570 --> 00:03:56,380 Now if we don't want that, we want to sample, 73 00:03:56,380 --> 00:04:00,460 let's say, without replacement, I could use a different function, 74 00:04:00,460 --> 00:04:03,280 one called random.sample. 75 00:04:03,280 --> 00:04:04,970 Random.sample. 76 00:04:04,970 --> 00:04:10,490 And this one has the same arguments, the first one being the list of cards 77 00:04:10,490 --> 00:04:13,530 to choose from, or really any list to choose anything from, 78 00:04:13,530 --> 00:04:18,260 and then k being the number of items we hope to select from this list. 79 00:04:18,260 --> 00:04:24,650 Now, like I said, random.sample will select without replacement. 80 00:04:24,650 --> 00:04:27,110 It will be akin to me having a deck of three, 81 00:04:27,110 --> 00:04:30,920 shuffling it, taking one card out, shuffling the remaining two, 82 00:04:30,920 --> 00:04:32,458 and choosing one more card. 83 00:04:32,458 --> 00:04:33,750 So let's see what happens here. 84 00:04:33,750 --> 00:04:37,520 I'll run Python of cards.py, and I'll get back 85 00:04:37,520 --> 00:04:40,050 queen and king, two distinct cards. 86 00:04:40,050 --> 00:04:44,060 I'll again do Python of cards.py, jack and king. 87 00:04:44,060 --> 00:04:46,230 And again, queen and king. 88 00:04:46,230 --> 00:04:50,870 So you can see here I'm getting a random set of choices from this deck, 89 00:04:50,870 --> 00:04:54,470 but because I only have one card for each, 90 00:04:54,470 --> 00:04:58,130 in this case, jack, queen, and king, I'll always get, 91 00:04:58,130 --> 00:05:00,990 at the end, unique choices from my deck. 92 00:05:00,990 --> 00:05:03,930 I'm here sampling without replacement. 93 00:05:03,930 --> 00:05:09,180 Now what if I wanted to maybe weight the odds a little more in my favor 94 00:05:09,180 --> 00:05:12,600 and make some things more likely to happen than others? 95 00:05:12,600 --> 00:05:17,190 Well, I can actually use, if we go back to random.choices, another argument 96 00:05:17,190 --> 00:05:21,450 to this choices function, one called weights. 97 00:05:21,450 --> 00:05:22,140 Weights. 98 00:05:22,140 --> 00:05:27,870 And weights takes as input this argument here, a list of values, numbers 99 00:05:27,870 --> 00:05:33,910 to be sure, the same length as the list that I'm selecting elements from. 100 00:05:33,910 --> 00:05:39,840 So let's say I wanted to currently make it more likely a user will 101 00:05:39,840 --> 00:05:42,100 choose the jack card. 102 00:05:42,100 --> 00:05:44,860 Well, I could do that by adjusting the weights here. 103 00:05:44,860 --> 00:05:47,130 Currently, if I didn't set weights at all, 104 00:05:47,130 --> 00:05:50,890 it would be equally likely that a user would choose jack, queen, or king. 105 00:05:50,890 --> 00:05:53,790 But I could weight things more, let's say, in my favor, 106 00:05:53,790 --> 00:05:59,100 and maybe make it so that the user 100% of the time will choose jack. 107 00:05:59,100 --> 00:06:00,990 And I can do so like this. 108 00:06:00,990 --> 00:06:05,860 Here, 100, indicating 100%, means that the user will always 109 00:06:05,860 --> 00:06:09,940 choose the jack card and 0 here, meaning kind of 0%, 110 00:06:09,940 --> 00:06:13,580 will be they'll never choose, in this case, queen or king. 111 00:06:13,580 --> 00:06:14,480 So let's run this. 112 00:06:14,480 --> 00:06:16,280 I'll do Python of cards.py. 113 00:06:16,280 --> 00:06:19,900 And here, well, unsurprisingly, we get jack and jack. 114 00:06:19,900 --> 00:06:23,080 And we'll run this again, we get jack and jack, 115 00:06:23,080 --> 00:06:26,090 and again, we get jack and jack. 116 00:06:26,090 --> 00:06:29,650 So it seems like I've weighted things more towards this jack card. 117 00:06:29,650 --> 00:06:31,250 But what else could I try? 118 00:06:31,250 --> 00:06:35,410 Maybe I could make it only a little bit more likely 119 00:06:35,410 --> 00:06:38,380 that a user chooses the jack card. 120 00:06:38,380 --> 00:06:40,630 And I'll then make it a little more likely 121 00:06:40,630 --> 00:06:44,690 they choose the queen card and king, let's put at about 5%. 122 00:06:44,690 --> 00:06:48,890 So to be sure these weights add up to 100%-- 123 00:06:48,890 --> 00:06:53,170 of course, we're always going to select at least one card from the options here. 124 00:06:53,170 --> 00:06:59,890 But it seems like 75% of the time, we'll get back a jack, 20% of the time, 125 00:06:59,890 --> 00:07:03,800 we'll get back a queen, and 5% of the time, we'll get back a king. 126 00:07:03,800 --> 00:07:04,880 So let's try this out. 127 00:07:04,880 --> 00:07:07,150 I'll run Python of cards.py. 128 00:07:07,150 --> 00:07:08,650 Again, get Jack and Jack. 129 00:07:08,650 --> 00:07:11,930 Python of cards.py, again, get jack and jack. 130 00:07:11,930 --> 00:07:16,750 And if we keep going, odds are we'll eventually, as we have down below, 131 00:07:16,750 --> 00:07:18,320 end up with a queen. 132 00:07:18,320 --> 00:07:21,070 But again, this is much less likely than it was before 133 00:07:21,070 --> 00:07:24,250 without having applied these weights. 134 00:07:24,250 --> 00:07:26,890 Now randomness is really fun, really cool, 135 00:07:26,890 --> 00:07:32,630 but it's not so fun and not so cool when you're trying to debug your programs. 136 00:07:32,630 --> 00:07:36,520 In fact, randomness can get in the way of debugging because really, you 137 00:07:36,520 --> 00:07:41,150 want to think of debugging as thinking of defined inputs and defined outputs. 138 00:07:41,150 --> 00:07:44,360 And if everything happens randomly, it's hard to debug your program. 139 00:07:44,360 --> 00:07:48,940 So thankfully, there are ways to have your programs work with randomness, 140 00:07:48,940 --> 00:07:54,050 but to guarantee certain outcomes when you want to do something like debugging. 141 00:07:54,050 --> 00:08:01,640 Now in the random module, there is, in this case, a function called seed. 142 00:08:01,640 --> 00:08:06,260 And a seed is something that goes into this thing called a pseudorandom number 143 00:08:06,260 --> 00:08:06,760 generator. 144 00:08:06,760 --> 00:08:10,270 It actually underlies the random choices that 145 00:08:10,270 --> 00:08:15,160 go into functions like choices, and sample, and choice that we've seen here. 146 00:08:15,160 --> 00:08:19,300 Now it turns out when you initialize a Python program like this one, 147 00:08:19,300 --> 00:08:22,180 or call a function like random.choices, you 148 00:08:22,180 --> 00:08:25,270 are using that pseudorandom number generator. 149 00:08:25,270 --> 00:08:28,120 And it takes as input something like a seed that 150 00:08:28,120 --> 00:08:32,409 might change on different runs of your program, like your system time. 151 00:08:32,409 --> 00:08:37,570 But if we give a seed that is a specific number that always stays the same, 152 00:08:37,570 --> 00:08:42,010 well, we'll always get the same choices from, let's say, 153 00:08:42,010 --> 00:08:45,760 a function like random.choices, or sample, or choice. 154 00:08:45,760 --> 00:08:47,410 Let's take a look at it here. 155 00:08:47,410 --> 00:08:55,670 I'll go down and I will say random.seed, and I'll give it here some number. 156 00:08:55,670 --> 00:08:58,130 Let's just say 0 for simplicity. 157 00:08:58,130 --> 00:09:03,140 Now normally, the seed would be set by something like my system time. 158 00:09:03,140 --> 00:09:05,490 It changes on each run of the program. 159 00:09:05,490 --> 00:09:11,650 But here, I want to define it explicitly as 0 every time I run this program. 160 00:09:11,650 --> 00:09:15,930 Well, I could go ahead and run Python of cards.py, 161 00:09:15,930 --> 00:09:19,840 and we'll see we get back king and king by chance. 162 00:09:19,840 --> 00:09:25,320 But now if I run Python of cards.py, I'll get back king and king again, 163 00:09:25,320 --> 00:09:28,260 and maybe again here, I'll get back king and king. 164 00:09:28,260 --> 00:09:32,100 So it seems like setting the seed has given me 165 00:09:32,100 --> 00:09:34,680 a random choice, certainly from this deck, 166 00:09:34,680 --> 00:09:37,555 but one that will always stay consistent. 167 00:09:37,555 --> 00:09:38,680 And I could try this again. 168 00:09:38,680 --> 00:09:43,590 I could do, maybe, a seed of 1, and see if that might change anything here. 169 00:09:43,590 --> 00:09:45,340 Python of cards.py. 170 00:09:45,340 --> 00:09:47,010 I'll get jack and king here. 171 00:09:47,010 --> 00:09:52,780 And I claim that as long as my seed is 1, I'll get back jack and king. 172 00:09:52,780 --> 00:09:55,290 So setting the seed here is a really good way 173 00:09:55,290 --> 00:09:57,790 to help you debug your programs. 174 00:09:57,790 --> 00:10:00,600 Your programs can involve randomness, but you can actually 175 00:10:00,600 --> 00:10:04,810 be sure of the outcome when you set something like a random seed. 176 00:10:04,810 --> 00:10:07,640 So this was our short on random. 177 00:10:07,640 --> 00:10:11,380 Feel free to use it to add an element of chance or randomness to your programs, 178 00:10:11,380 --> 00:10:13,880 or whenever you want to set the odds in your favor. 179 00:10:13,880 --> 00:10:15,830 This was our short on random. 180 00:10:15,830 --> 00:10:18,300 We'll see you next time. 181 00:10:18,300 --> 00:10:20,000