1
00:00:04,818 --> 00:00:10,543
There are three methods we can use, to delete
items from a set. There's also a clear method,

2
00:00:10,543 --> 00:00:15,019
which works the same as it does for lists
and dictionaries - it clears the set, deleting

3
00:00:15,019 --> 00:00:20,619
all the items in it.
I've created a new Python file called remove_items_set,

4
00:00:20,619 --> 00:00:24,660
for these examples.
Rather than typing in a load of numbers, we

5
00:00:24,660 --> 00:00:30,113
can pass a range to the set function. I'll
type the code to do that, and print the result:

6
00:00:45,973 --> 00:00:50,920
Run the program.
We get a set containing all the integers from

7
00:00:50,920 --> 00:00:56,333
zero to 20, inclusive.
The values appear in order, but don't be fooled!

8
00:00:56,333 --> 00:01:00,126
Sets have no ordering.
Python has to print them out in some order,

9
00:01:00,126 --> 00:01:04,471
and will sometimes display a set of integers
in order. But don't think that means the set

10
00:01:04,471 --> 00:01:08,604
is ordered – it isn't.
This is an effect of the way sets are implemented,

11
00:01:08,604 --> 00:01:14,523
in CPython. If you're using a different implementation
of Python, you may get different output.

12
00:01:14,523 --> 00:01:18,435
I've deliberately used strings in the previous
examples, because they make it clear that

13
00:01:18,435 --> 00:01:22,070
the sets are unordered.
When you have a set of integers, it can be

14
00:01:22,070 --> 00:01:24,317
less obvious that there's no order to the
set.

15
00:01:24,317 --> 00:01:32,499
So let's check out the documentation about
sets. I'll go to that page in my browser.

16
00:01:36,281 --> 00:01:42,031
The first sentence makes it clear: "A set
object is an unordered collection of distinct hashable objects".

17
00:01:42,031 --> 00:01:46,766
A particular set might print out in order,
but it's still an unordered collection.

18
00:01:46,766 --> 00:01:51,168
If you write code that relies on items being
in order, then your code will break!

19
00:01:51,168 --> 00:01:56,399
Alright, I wanted to clear up any confusion
about that. Let's go back to our code.

20
00:01:56,399 --> 00:02:01,509
Like lists and dictionaries, Python sets have
a clear method. It removes all the items in

21
00:02:01,509 --> 00:02:07,249
the set, leaving an empty set.
I'll type the code to clear the set, and print the result:

22
00:02:18,785 --> 00:02:20,589
Run the program:

23
00:02:21,821 --> 00:02:26,389
As expected, we get an empty set.
Notice that the output isn't an opening and

24
00:02:26,389 --> 00:02:31,860
closing pair of curly braces. That would look
like a dictionary, so Python 3.9 prints set

25
00:02:31,860 --> 00:02:36,592
and parentheses. Different versions may display
curly braces instead.

26
00:02:36,592 --> 00:02:40,700
There's not much else to say about clear.
If you want to clear out all the items in

27
00:02:40,700 --> 00:02:44,610
a list, a dictionary or a set, call the clear
method.

28
00:02:44,610 --> 00:02:49,510
I'll comment out those 2 lines, because we
need some items in our set.

29
00:02:49,510 --> 00:02:54,419
To delete individual items, you can use the
remove or discard methods.

30
00:02:54,419 --> 00:02:59,290
They both do the same thing – they remove
an item from the set. The difference is that

31
00:02:59,290 --> 00:03:01,813
remove will raise an exception if the item
isn't present.

32
00:03:02,150 --> 00:03:07,557
Some examples will demonstrate the difference.
I'll type the code after those lines I commented out: 

33
00:03:27,398 --> 00:03:33,121
Ok, run the program, and 10 and 11 are no
longer in the set.

34
00:03:33,121 --> 00:03:38,686
Let's see what happens if we discard an item
that doesn't exist. I'll add the code to the end of our program:

35
00:03:52,200 --> 00:03:55,190
Run the program:

36
00:03:55,190 --> 00:04:01,211
That works fine. 99 wasn't in the set, so
calling discard doesn't change anything.

37
00:04:01,211 --> 00:04:05,582
That's not the case if we use remove. I'll
type that code next:

38
00:04:19,507 --> 00:04:25,000
This time, when I run the program, it crashes
with an error on line 14.

39
00:04:25,894 --> 00:04:30,720
As the Zen of Python says, "There should be
one – and preferably only one – obvious

40
00:04:30,720 --> 00:04:34,710
way to do it".
So why do we have both discard and remove?

41
00:04:34,710 --> 00:04:36,590
We've just seen the difference in their behaviour,

42
00:04:36,590 --> 00:04:39,810
and it is an important difference.

43
00:04:41,027 --> 00:04:46,249
There are two different things we might want to do,
and having two different methods reflects that:

44
00:04:46,249 --> 00:04:52,636
1: Ensure that, when we're done, something
no longer exists. In this case, we don't care

45
00:04:52,636 --> 00:04:55,440
if it was already there or not – we just
want it gone.

46
00:04:55,440 --> 00:05:00,448
2: Remove something if it exists, but provide
some sort of notification if it doesn't.

47
00:05:00,448 --> 00:05:05,082
These are different use cases, and Python
provides an obvious way to do each one; 

48
00:05:05,082 --> 00:05:09,460
discard for the first case, and remove for the second.

49
00:05:10,999 --> 00:05:16,570
Airports restrict the items that you can carry in hand luggage.
If you're very well organised, you might run

50
00:05:16,570 --> 00:05:21,139
your packing list through a Python program,
before packing. You might have the following

51
00:05:21,139 --> 00:05:28,121
set of things that you can't take:
Restricted items equals gun, catapult, blade, scissors.

52
00:05:28,121 --> 00:05:31,536
That's not the full list, but those will do for our example.

53
00:05:31,536 --> 00:05:34,037
So your Python program will iterate over that set, 

54
00:05:34,037 --> 00:05:38,259
and remove anything it finds from your
set of items to pack.

55
00:05:39,783 --> 00:05:44,719
The code might look something like this:
For items in restricted items; packing set

56
00:05:44,719 --> 00:05:49,648
dot discard, item.
We loop through the items in the set of restricted items,

57
00:05:49,648 --> 00:05:52,950
and discard any restricted items from
our packing set.

58
00:05:52,950 --> 00:05:58,030
Using discard there is fine. If you haven't
included the item in your packing set, discard

59
00:05:58,030 --> 00:06:04,572
won't raise an exception. The code just moves
on to the next item.

60
00:06:04,572 --> 00:06:09,280
Using remove wouldn't be a good idea. When
it failed to find "catapult" in the list of

61
00:06:09,280 --> 00:06:12,393
things you intend to pack, the code would
crash.

62
00:06:12,393 --> 00:06:15,830
This is an example of when you don't care
if something is in the set or not – you

63
00:06:15,830 --> 00:06:20,389
just want to make sure it's not there, after
the code has executed.

64
00:06:21,796 --> 00:06:27,564
Lets assume we've created a list of sets.
The sets contain the medications that patients are taking,

65
00:06:27,681 --> 00:06:31,706
and our intention is to replace
the blood thinning drug warfarin with edoxaban.

66
00:06:31,706 --> 00:06:36,120
Both drugs thin the blood to prevent blood
clots, but edoxaban has some advantages over

67
00:06:36,120 --> 00:06:39,050
warfarin.
I'm going to assume that we've already identified

68
00:06:39,050 --> 00:06:42,356
those patients who would benefit from changing
their medication.

69
00:06:42,356 --> 00:06:47,370
And yes, this is a bit contrived . But it
also does represent a real situation that

70
00:06:47,370 --> 00:06:50,720
could arise.
So our code has to remove warfarin from the

71
00:06:50,720 --> 00:06:53,988
set of medications that each patient is taking.

72
00:06:55,645 --> 00:07:02,317
The aim here, is to replace one anti-coagulant drug with another.
That means we can't just use discard.

73
00:07:02,317 --> 00:07:07,189
When we come to remove warfarin, it's important
that the patient was actually taking it.

74
00:07:08,948 --> 00:07:14,639
In this case, it's better that our code crashes.
Otherwise, we could end up prescribing the

75
00:07:14,639 --> 00:07:19,450
anti-coagulant drug, edoxaban, to someone
who didn't need an anti-coagulant.

76
00:07:19,450 --> 00:07:23,879
remove is a better option here.
If we attempt to remove warfarin, and the

77
00:07:23,879 --> 00:07:27,710
patient wasn't taking it, that's a situation
we need to be alerted to.

78
00:07:27,710 --> 00:07:32,100
When we use remove, we'll get an error, if
warfarin isn't in the set of medications that

79
00:07:32,100 --> 00:07:34,622
the patient was taking.

80
00:07:36,366 --> 00:07:41,899
Now I'm not suggesting that you write code that you
know will crash. That's not the point of all this.

81
00:07:41,899 --> 00:07:49,249
The point is that remove will let us know, if we try
to delete something that doesn't exist. discard won't.

82
00:07:50,656 --> 00:07:53,009
Later, we'll see how to handle the exception

83
00:07:53,009 --> 00:07:56,869
that remove causes, when you try to remove
something that doesn't exist.

84
00:07:56,869 --> 00:08:00,690
At the moment, we're looking at why there
are two different methods to delete an item

85
00:08:00,690 --> 00:08:03,409
from a set.
So that's the reason why.

86
00:08:03,409 --> 00:08:08,550
In the next two videos, we'll look at the
code for both these methods. Examples will

87
00:08:08,550 --> 00:08:12,434
make the difference clear, and give an idea
of when you should use each method.

88
00:08:12,434 --> 00:08:15,380
I'll see you in the next video.

