back to index

6 of Python's Newest and Best Features (3.7-3.9)


Chapters

0:0 Intro
0:35 Breakpoint
1:57 Walrus Operator
6:28 Sign specifier
7:43 Positional parameters
10:56 Type hinting
16:26 Dictionary unions

Whisper Transcript | Transcript Only Page

00:00:00.560 | Hi and welcome to this video, we're going to go through
00:00:03.600 | and take a look at some of the coolest, more interesting
00:00:07.360 | features that have been added into Python in the past few years.
00:00:11.200 | So we'll just go straight into it and code a few examples as well.
00:00:15.760 | Okay so the first one and the only example we're going to look at from
00:00:19.360 | Python 3.7 is the addition of breakpoints.
00:00:24.160 | So obviously a breakpoint is where we typically click
00:00:28.240 | on the left side of our editor to add in the little red circle, which means we
00:00:32.720 | want the code to break at this point. What the breakpoint function allows us
00:00:38.160 | to do is actually use Python debuggers within our code.
00:00:42.960 | So the function uses the bdb debugger by default
00:00:47.520 | but we can also use other alternatives as well.
00:00:51.200 | So for example if we had a list of functions here, a list of
00:00:56.080 | print statements.
00:00:58.960 | Okay so they just print out "hello". If we for whatever reason
00:01:06.160 | wanted to put in a breakpoint to try and figure out what was going wrong,
00:01:10.560 | say this code was probably a little more complicated,
00:01:14.560 | we could add in this.
00:01:17.440 | Okay and then we go straight into the Python bdb
00:01:22.240 | debugger at the bottom here and this is essentially like a
00:01:26.000 | interactive shell where we can just write Python and
00:01:29.200 | figure out what is going on. So obviously there's not really much for us to figure
00:01:33.680 | out in this case but when you're actually writing
00:01:37.840 | more complex functions or classes or modules in your
00:01:41.360 | code this can be really really useful. So here we can print
00:01:49.200 | or do anything. It's simply an interactive Python debugger window.
00:01:57.600 | So the second of our new features actually comes from Python 3.8.
00:02:03.280 | Now this is the walrus operator which was the go-to for the majority of 2019
00:02:09.440 | for anyone covering what is new in Python 3.8.
00:02:13.840 | So it's a new operator added to Python. It's genuinely very useful.
00:02:19.040 | It essentially allows us to assign a value to a variable on the fly.
00:02:23.520 | So it looks like this which looks like a walrus hence the name
00:02:26.880 | and we can use it to write more compact code.
00:02:31.440 | So say we have a list here and we want to
00:02:35.680 | assign the length of this list to a variable
00:02:40.080 | which we'll call t_length
00:02:43.280 | and then we want to write an if statement checking
00:02:48.480 | if t_length is greater than 3.
00:02:52.640 | And if so we want to print out the length t_length
00:02:59.920 | and a little statement saying that this is greater than 3.
00:03:05.440 | That's great. With the walrus operator we can actually make this more
00:03:18.400 | compact and include our variable assignment
00:03:21.760 | within the if statement.
00:03:25.840 | So we put this within a bracket and then we change our equal sign here
00:03:31.040 | to a walrus operator and we can run that again
00:03:35.440 | and now we have four is greater than three.
00:03:38.640 | So then we've shortened our code made it more compact.
00:03:43.200 | Obviously you know whether this is useful and more readable
00:03:47.520 | is completely up to who is writing the code.
00:03:51.440 | Nonetheless it's a very useful operator to
00:03:54.400 | understand and use. So a more realistic use case for this could be
00:04:01.040 | if we are writing a regex statement. So I'll just write out a sentence here
00:04:06.640 | quickly.
00:04:14.960 | Okay so we want this sentence to go through and
00:04:19.600 | use regex to find a currency followed by a few numbers.
00:04:22.960 | So I'll just switch this to dollars here.
00:04:28.320 | So we're going to go through each of these sentences and only print out the
00:04:31.680 | ones that contain a currency.
00:04:35.520 | We also need to import re for regex.
00:04:44.640 | Now for those of you that use regex a fair bit before
00:04:48.240 | you'll know that when we use a regex search it will
00:04:51.600 | return either none or return a set of groups which contain
00:04:56.400 | our matches and typically what we'd have to do
00:05:00.320 | is we'd have to write amount equals re.search and then we would have
00:05:07.600 | our regex in here. So here I'm just going to
00:05:13.920 | do a lookup.
00:05:16.800 | So this is just checking for a dollar symbol
00:05:22.480 | before a set of digits and this will return just digits not the
00:05:29.200 | dollar symbol.
00:05:31.840 | Okay and usually you would have to do this and then we would have to write
00:05:38.240 | if amount
00:05:41.280 | or just if amount is true and then print out the amount and the
00:05:48.720 | group which would be zero
00:05:52.960 | and then we would get our results.
00:05:57.920 | This should be sentences. Okay so we get 100
00:06:03.840 | but what we can do instead is use our walrus operator.
00:06:09.120 | If amount
00:06:14.640 | and now we've shortened our code. So that's more probably a more useful
00:06:24.400 | example of using the walrus operator. Another really cool feature that was
00:06:31.200 | added in 3.8 is the fstring equal sign
00:06:35.760 | specifier. So I'll give a quick example.
00:06:41.680 | So we have these two variables it's just two numbers
00:06:47.040 | and maybe we are trying to figure out maybe we're doing something wrong and we
00:06:51.520 | want to see where our values are going and what
00:06:54.720 | variables are being assigned to and what we might typically do
00:06:58.320 | is this.
00:07:01.440 | We might write x equals x
00:07:07.920 | and y equals y.
00:07:13.440 | Okay and this is probably what a lot of us would do
00:07:19.360 | but rather than doing this we can actually just write
00:07:25.440 | x equals like this
00:07:30.560 | and this will print out the same thing. So it shows the variable name and the
00:07:37.040 | value within it. So it's a smaller but I think very useful addition to Python.
00:07:44.480 | Okay so the final feature from Python 3.8 is the inclusion
00:07:48.240 | of syntax to specify the input parameters the functions that cannot be
00:07:53.920 | called by name but instead by the position. So what I
00:07:58.240 | mean by that is if we have
00:08:02.720 | this function here
00:08:05.600 | we can either write this
00:08:20.880 | which is using the position of the parameters in order to
00:08:24.240 | fill in those variables or we can also do this
00:08:30.640 | and we'll get the exact same output. Now this is great but when you're writing
00:08:45.280 | code that other people are using and relying on and maybe that
00:08:49.600 | code isn't completely finished yet you may find
00:08:52.640 | that you are not entirely sure if you'll keep
00:08:54.800 | this variable or input parameter as op or this is x or this is y you might
00:09:01.120 | change these around and if people are using your code like
00:09:04.960 | this that will cause problems when you do
00:09:08.320 | change your code to use different variable names.
00:09:12.080 | So maybe at a later point you decide you would change your code to
00:09:16.880 | use method instead of op. If we took that and then tried to use this
00:09:22.960 | function again we'd get this type error. Obviously we
00:09:28.320 | don't want that so what we can do instead
00:09:33.520 | is define method as a positional only parameter and we do that
00:09:40.720 | by adding this slash. So now if we try to run this
00:09:45.920 | but with operator again
00:09:50.000 | we see okay we have a type error count got some positional
00:09:58.480 | only arguments passes keyword arguments. So although we haven't changed
00:10:03.040 | operator to method yet we are preventing the user
00:10:06.640 | from using op here. So that forces the user to use this
00:10:12.400 | instead.
00:10:15.680 | Now the user can still define these
00:10:20.000 | using their names that's completely fine
00:10:28.800 | but they cannot use anything that comes before this slash. So if we
00:10:34.480 | do rewrite our function to use method instead of op
00:10:43.520 | and the user runs their code that they've been using before
00:10:47.760 | we won't get any errors because we've prevented the user from being able to
00:10:51.760 | use this keyword parameter.
00:10:56.480 | Okay so that's everything for Python 3.8 and we're going to move on to Python
00:11:00.720 | 3.9. Now the main one of those
00:11:05.600 | is the addition of more type hinting. So type hinting is something that has been
00:11:09.680 | around for a while and it seems to be a recurring theme
00:11:13.440 | with every Python update that we will get some new
00:11:16.880 | type hinting functionality. For Python 3.9
00:11:20.800 | they've essentially merged all the different type hinting
00:11:24.240 | features that they've been adding over time and brought them into the core
00:11:28.000 | Python functionality. So there's no more importing
00:11:31.680 | typing modules or annotation modules just works
00:11:35.120 | as it is for the most part. So for those of you that don't know what
00:11:40.720 | typing is in Python
00:11:44.000 | say we have this function here
00:11:48.720 | it's quite clear that this function add_int
00:11:58.960 | shouldn't be used with strings.
00:12:03.280 | Okay but it can be used because we're just using a plus here so
00:12:08.560 | it's essentially telling Python to concatenate these two strings but our
00:12:12.320 | intention is actually to only allow integers.
00:12:15.680 | So what we can do is add a type annotation or a type hint
00:12:23.680 | and that's what this is here. So we add this colon followed by
00:12:27.280 | the data type that we intend this value to be.
00:12:30.880 | Then we return a plus vowel.
00:12:37.920 | Now when you are writing this code out in your editor
00:12:43.600 | and you have your Python linter so pylint for example
00:12:48.000 | it will come up with an error if you write something like this
00:12:52.640 | later on. And this isn't an error that will stop
00:12:55.840 | your code. We can still run it. It is just a hint, it is a warning. Okay you
00:13:01.920 | can't see it here because we're in Jupyter but in a normal editor with
00:13:06.560 | pylint installed you will see this bit here get highlighted
00:13:12.480 | with a note saying we expected type
00:13:18.720 | type int got string instead. Okay so that's
00:13:27.440 | the warning that will pop up. Now this is just
00:13:30.720 | very useful for complex code bases where you're not entirely sure
00:13:34.880 | what values are supposed to be going in and out of different functions and
00:13:38.720 | classes. Just makes things a lot easier to
00:13:41.920 | follow. Another syntax addition in terms of the
00:13:47.200 | type hinting that was added is the ability to
00:13:50.000 | define the type that should be coming out of a function not just into a
00:13:53.680 | function.
00:13:56.160 | Say here we want to sum up all the values within a
00:14:03.280 | dictionary.
00:14:05.920 | We want to input a dictionary and what we would expect to get out of
00:14:12.320 | this which is defined by this little arrow
00:14:14.400 | syntax here as an integer. Then we just return the sum
00:14:22.560 | of the values within our dictionary.
00:14:27.760 | Then we define our dictionary here and we can also add the type here as
00:14:39.280 | well.
00:14:46.560 | Then we call our function and we should get a
00:14:53.200 | integer out of that as expected. Now if we change this and these were the
00:14:59.600 | other way around and we had strings instead of numbers here we would
00:15:04.000 | obviously get a full-blown error but before we
00:15:06.880 | even ran that we would see a type hint come up
00:15:10.800 | saying okay we are expecting a integer here
00:15:14.080 | not a string. So it can be very useful and just
00:15:17.920 | in terms of readability it can depending on how you do this be very
00:15:24.080 | very useful. If you look into complex libraries
00:15:27.200 | like you have the TensorFlow library or Transformers library those libraries
00:15:30.880 | with type hints can make things a lot easier.
00:15:33.200 | In fact some of the more recently written code in the Transformers library
00:15:38.800 | has been using type hinting and it makes it so much easier to read.
00:15:44.000 | So it's a very good addition to Python in my opinion.
00:15:48.960 | Now something that is very useful if we take this function again
00:15:55.120 | we can actually use more complex types. So we know that we want a
00:16:02.000 | dictionary but maybe you want to define what is
00:16:04.640 | within that dictionary as well. So we can actually do that like this.
00:16:09.760 | So now we know that our dictionary should be built of string keys
00:16:16.400 | and integer values and this is just an extra layer of detail so we can be
00:16:22.880 | more specific. There we go. Now the final feature in Python 3.9 that
00:16:30.320 | we'll go over is dictionary unions operators.
00:16:34.880 | There's quite an interesting addition to the syntax
00:16:38.320 | and it gives us two new operators. One is called the merge operator
00:16:42.720 | and the other is the update operator. So the merge operator looks like this
00:16:48.560 | and we use it to merge two dictionaries. So let's write out two
00:16:54.400 | dictionaries quickly.
00:16:59.040 | Okay so we have these two dictionaries and we can merge them using our merge
00:17:02.880 | operator.
00:17:05.360 | Okay and now we can see that those two dictionaries are now one
00:17:15.120 | within our new variable C. The update operator is slightly different
00:17:19.680 | in that it allows us to do the merge in place.
00:17:23.600 | So what that means is rather than adding this to a new variable
00:17:30.240 | we actually assign it to the variable on the left of the statement and this here
00:17:37.120 | is the update operator. Now if we print A
00:17:43.040 | we see that we get the same function. Okay so that's it for this video
00:17:49.200 | covering some of the biggest changes and upgrades
00:17:52.160 | to Python that we actually see and use on a daily
00:17:56.160 | basis. But that's it for this video, I hope
00:17:59.680 | you've enjoyed and as always thank you for watching, bye!