Transcription
This video was brought to you by IND dentle IO learning Python Made Simple. How's it going, everyone?
About 4 years ago, I made a Python crash course which recently blew up. And I thought, 4 years is a lot of time, so it's time to make an updated course. And this video will be useful if you are a beginner. The only two requirements I have for this video is that you have Python installed and you have your own code editor installed. For this tutorial, I'm going to be using PyCharm. It's completely free and you can find it on the JetBrains website.
Anyway, let's get started. The very first thing we're going to learn is how to run our very first script. So here, we're going to type in one of the most popular commands in any programming language, and that is: print("hello world"). As you can see, I'm using some quotation marks followed by some text, and this is important when you want to insert text into Python. And with print, we can finally run this script by tapping on the green arrow. And you'll see that inside the console, we're going to get this as an output. So we essentially told Python to display this information. And we can change this to anything we like. We can even type in "hello Bob". And I'm using a shortcut, which is Command + R, to run my scripts. If that doesn't work for you, you're going to have to go to settings, then go to the key map, and type in "run". Then, inside here, you'll find a section called "Run and Debug". And what you want to select is the "Run" feature and assign it your own shortcut.
Anyway, I'm going to be using that shortcut from now on. So here, we can change the text to whatever we like. But it would be so much nicer if we could edit this in another place. So what we're going to do next is create a variable. And here, we're going to call this variable "name". And the name is going to be set to "Bob". So now, all we need to do is replace this section here with this variable. And to do that, I'm going to remove "Bob", I'm going to type in `+ name + "!"`. And this is going to perform a string concatenation, which means "name" is going to be added to "hello", and the exclamation mark will be added to "name". Which means now, when we run this, we're going to get "hello Bob!". And it would be nice if we had a space there. But what's nice about this approach is that if we were to duplicate this line and we were to change this to "James", "name" will always stay up to date with the name that we defined here. So now it's going to print "hello James", "hello James" without us having to type in "James" twice. Variables are great for reusability and it makes writing code so much easier.
Anyway, moving on, I want to talk about the data types we have in Python. Because up until now, we've been working with strings, and strings are just text. But we have many other data types. So let's take a look at all of them. So as I mentioned, the first data type we encountered was a string, which is just some text. So for example, here we can have some text which contains the value of "Apple". Then a number is referred to as an integer in Python, and that can be any whole number. So 10 or -10, that is an integer. If you want to have a decimal, this is referred to as a float, and that's any decimal number. So 10.5 or 10123, that's going to be considered a float. Then we have something called a Boolean, which is either true or false. So for example, `has_money = False`. And again, this only has two states: false and true.
Next, we have something called a tuple, and a tuple looks like this: `(2.5, 1.5)`. It's just a list-like structure which you cannot change after you create it. So this contains two coordinates, but you can even add more coordinates. You can add, I don't know, `1.0`. Now it will contain three coordinates. Then we have a list, and here we're going to create a variable called `names`, and that's going to contain `["Aneta", "Bej", "Benny", "Anif"]`. And to create a list, you just need to use square brackets. And this data is mutable, which means we can remove elements and add elements, unlike with tuples, where the data is immutable, which means, once again, once we create this, we cannot change it.
Next, we have something that's called a set. So here we're going to type in `unique = {1, 2, 3, 4, 4, 5}`. Now, the reason I called this unique is because a set cannot contain duplicates. I mean, you can insert duplicates, but as soon as you print this to the console, you'll notice that the duplicate of 4 will disappear. So it's another list-like structure that cannot contain duplicates. And finally, we have something that's called a dictionary, and a dictionary is a list-like structure that holds key-value pairs. For example, here we might have a user called "Bob" with the value of 1, or the ID of 1, and "James" with the ID of 2. As you can see, each element contains a key and a value. So both of these are associated with each other, and that's one element in the dictionary.
Sometimes in Python, you're going to be presented with one data type which you're going to want to convert into another data type. For example, sometimes you're going to try to scrape some information from the internet, and what you're going to get back is, let's say, a number in the form of a string. Now, the problem with this is that you can't use it as a regular integer. With a regular integer, you can do `10 + 10`, for example, and that will give us back 20. But if we were to do `10 + number`, we're going to get an error because this type can only be added with other strings. So in Python, you can attempt to convert any data type into another data type by using the type constructor. And a type constructor is literally just the type you want to turn it into, followed by a pair of parentheses. So here, we're attempting to convert `number` into an integer, and that's going to work perfectly fine because 100 is actually a number. If we were to type in `"10"`, it's going to give us a `ValueError` because `"10"` is not an integer, it is text that represents the number 10 that only a human can understand. So for this to work, we need to add an actual number. And as I mentioned earlier, you just need to pass in the type you want to convert it to. So it can be a string, or a float, or a set, whatever data type you want to convert this variable into, you just put the data type in front of it, followed by parentheses. And I mean, you don't have to actually use a variable, you can absolutely type it in directly here: `float("123.456")`. And this will convert this string into a float.
Now, a very good practice for writing code is using type annotations. This is something I want to teach you as early on as possible because it's going to save you a lot of trouble in the future. But in Python, it's not required. You can type in something such as `age = 10`. But something you'll see me doing in all of my lessons is annotating it with the data type. Here, I'm explicitly telling Python that I want this to be of type integer: `age: int = 10`. And we might even have something called `first_name: str = "Bob"`. These are type annotations, and they tell the code editor or the static type checker what we're trying to do here. Python is going to ignore these, which means that if we were to type in `age: str = 10`, we're still going to be able to run this code with no problems. But what you're going to notice is that the code editor is going to tell us that we messed up. So this is a tool used for the developer. It tells us when we're making mistakes. Without this type annotation, we can add 10 here, we can add a string here, we can add whatever we want, and we're not going to get any errors because `age` can be literally anything. But by providing the information that `age` should be of type integer, we will get some warnings that we're doing something silly here, so that we'll have the chance to actually correct it. So you're going to see me using type annotations everywhere. It's not required, but I prefer to do this because I think it's professional and it saves me a lot of effort.
Anyway, here I'm going to remove the first part of `name` because for the next example, I want to teach you a very convenient concept called f-strings. Because earlier, I showed you that we could do something such as `print("Hello " + name + " you are " + str(age))`. And we need to make sure that this is actually a string. So what we have to do here is convert that to a string. And with that, when we run this, we will get some nice output such as this one: "Hello Bob you are 10". But this took a lot of effort and is not intuitive. We want to be able to write this in a much more fluent way. And luckily, Python provides us with the opportunity to use f-strings in these situations, which makes creating complex strings such as this one a lot easier. So instead of doing all of that, what we're going to do is `print(f"Hello {name} you are {age}")`. And the "f" here stands for "format". And f-string is a formatted string. Also, just to digress real quickly, you're not required to only use single quotation marks, that's just a simple preference of mine. You can also use double quotation marks if you want, that's up to you. I just got accustomed to using single quotation marks because I think it looks cleaner. But now, with that, we can type in `print(f"Hello {name} you are {age}")`. And using curly brackets, we can insert variables directly. So `name` and then `age`. This was just so convenient to type compared to the other string that we tried to concatenate. And watch what happens when we run it. It's going to run exactly the same way, or I mean, the output is going to be exactly the same. So I recommend using f-strings whenever you can because this is just hard to keep track of. You won't see many professional Python developers using this.
Moving on, it's time we learn about functions. And functions are used to make our code much more reusable, just like with variables. And to create a function in Python, we use the `def` keyword, which stands for definition or define. And immediately after that, you add a function name. So here, we're going to create a function that takes two inputs or two arguments, A and B, and then it's going to add those together. So `a` is going to be of type float and `b` is going to be of type float as well. Now, using this arrow, we can tell Python what we expect to return, and here we expect to return a float because adding `a` to `b` will return a float. Then, inside here, we can `return a + b`. And with that being done, we can `print(add(10, 15))` then we can duplicate this and say `print(add(15, 30))`. And when we run that, we're going to get the sum of both of those operations. And what's great about this is that we can reuse this function anywhere in our script as many times as we like. And it is as simple as that. Now, you might be asking, why didn't we just do `10 + 15` and `15 + 30`? Well, this works perfectly fine, but imagine we want to change something in the implementation of the function. If we want to add some other code in here, we're going to have to do it manually for each one of these. But now, let's go back to what we had earlier, and inside the function, what we're going to do is print that we are adding: `print(f"Adding {a} + {b}")`. I want to make this an f-string. And this change will be added to each function call. As you can see, now we have "Adding 10 + 15" and "Adding 15 + 30". So any change we bring to the function will be added to each function call, which is very convenient.
But let's take a look at another example. And this example, we're going to create a function called `greet` which will take a `name` of type string and a `greeting` of type string, and this will return `None` this time because we are only executing code. So `print(f"{greeting}, {name}")`. And what's great about this is that we can type in `greet("Bob", "Hi")`. And now when we run this, we're going to get our simple greeting back. But something else I want to show you is that we can also define default values by using the equal sign directly on the parameter. And this will make it so we don't have to define a greeting each time we use the function. Which means the next time we can type in `greet("James")` and it won't require us to actually supply a greeting. As you can see, it's going to say "Hi James" because "Hi" was the default for greeting. And we can also do that with `greet("Bob")` once again, the default will be used once again because we did not include greeting as an argument. And I don't know if this was obvious or not, but I'm just going to go over it anyway. When you're creating a function, you're not required to add any parameters. You can just say it's a function that executes some code, such as `def say_hello(): print("Hello")`. Then you can just call that function as many times as you want, and it will execute that code each time. And once again, type annotations are optional. They do not affect how your code is run, but help the code editor with understanding what you're trying to do.
Now that we understand how functions work, let's move on to looping in Python. And in Python, we have two different kinds of loops: one is the `for` loop and one is the `while` loop. For loops are used for finite looping, while while loops are used for infinite looping. So let's take a look at a couple of examples to see the difference and how they actually work. And first, I'm going to start with the `for` loop. So to create a `for` loop, we use the `for` keyword. And here we can add a variable name, which in general is going to be set to `i` if you're just going through a range. So here we're going to type in `for i in range(3): print("hello")`. And `range` is going to create a range of three numbers, which means it's going to loop three times. And once we run this, you'll notice that it's going to say "hello" three times. If we change this to `range(5)`, it's going to loop through the range of five numbers and it's going to print "hello" five times. And usually, you'll see `for` loops being used a lot with lists. For example, earlier we had this list of names: `names = ["Aneta", "Bej", "Benny", "Anif"]`. With a `for` loop, we can say `for name in names: print(f"Hello {name}")`. So this is going to grab each name from that list and use it for each iteration, which means now when we actually run this, we're going to get "Hello Aneta", "Hello Bej", "Hello Benny", and "Hello Anif". So as you can see, `for` loops are always used with a finite list of elements. And it doesn't have to be one statement, you can even add two statements: `print(f"Hello {name}")` and `print("...")`. As you can see, now we have two lines of code inside this `for` loop, and it will be executed four times because this list contains four elements.
Anyway, moving on, we have the `while` loop. As I mentioned earlier, the `while` loop is infinite, which means if we were to type in `while True: print("hello")`, this will be executed for as long as your computer exists. As you can see, there's no end to this condition. `True` is true forever, which means Python will execute this code over and over again until the end of all things. So right there, I force stopped the script because there's no point in having that run forever. Usually, with `while` loops, you're going to have some sort of condition, such as `while i < 3:`. And this is a condition which will eventually turn false. We actually need to create that above: `i: int = 0`. Now, here we can `print(i)` and for each iteration, we're going to type in `i = i + 1` or `i += 1`. So `i` is going to increment one on each loop, meaning that one day this is going to become 3, which is not less than 3. And once this evaluates to false, it's going to exit out of this `while` loop. As you can see, now when we run this, we're going to have 0 printed, 1 printed, 2 printed. But as soon as `i` contains the value of 3, this statement or this expression evaluates to false, which means the `while` loop will no longer continue with its loops.
Now, up next, we're going to talk about these comparison operations because there are quite a few that you're going to have to memorize. And in this example, I'm going to have two integers, one called `a` and one called `b`, and one will contain the value of 1 and the other one the value of 2. And I'm going to type these out real quick because they are self-explanatory. The first check we're going to do is whether `a` is more than `b` or greater than `b`, and we do that using the right arrow: `a > b`. We can also check that `a` is greater than or equal to `b`: `a >= b`. So if `a` contains the value of `b`, it's also going to evaluate to `True`. Right now, if we were to run this, we're going to get `False` for both of them because `a` is not greater than `b`. But if we add `a = 2` here, the first expression is going to evaluate to `False` because `a` is not greater than `b`, it's exactly the same as `b`. But with greater than or equals to, this will evaluate to `True` because `a` is equal to `b`.
Anyway, this also works in the opposite sense. So you can check that `a` is less than `b`: `a < b`, or whether `a` is less than or equal to `b`: `a <= b`, and that's going to work exactly the same way. Something else we can do is check whether `a` is equal to `b`: `a == b`, whether these two contain the exact same value. Right now, if we were to run this, we're going to get `False` because 1 is not equal to 2. But if we insert `a = 2`, we will get `True` as a return. And we can also do the opposite here. We can check that `a` is not equal to `b` by using the exclamation mark: `a != b`. And just like that, we're going to get `True` as an output because `a` is not equal to `b`. So these are the comparison operations that you should memorize because you'll be using them a lot throughout your programming career.
Up next, we're going to be talking about `if`, `elif`, and `else`, which is used for control and flow logic. Now, for this example, we're going to simulate that we're getting some user input. So here we'll type in `user_input: str = "hello"`. Now, if the user input is equal to `"hello"`, we will print that the bot says "Hello!". `elif user_input == "how are you":` we will say that the bot says "Good, how about you?". And in every other situation, we're going to use the `else` block. So if what we type in doesn't match any of these conditions, the `else` block is going to be executed. And here we can print that the bot says "Sorry, I did not understand that.". And just like that, we can try running this script. And what we should get as an output is that the bot says "Hello!". Otherwise, if we change this to `"how are you"`, the bot should respond "Good, how about you?". And if we type in something random, you'll see that the bot will not understand what we wrote. So with `if`, you can add any expression that you want to check for, and this code will only be executed if this evaluates to `True`. `elif` stands for "else if", which means if this doesn't pass, it's going to try to check whether this will pass. And if it does pass, it will execute this code. `else` will be executed in any other situation. And what's important to note is that you can have as many `elif` statements as you want. So you can also check that `user_input == "buy"`, then the bot can say "Goodbye!". Now, when we actually enter `"buy"` as an input, the bot's going to be able to respond with "Goodbye!".
Now, if you want to see something really cool, all we need to do here is type in `input(">>> ")` which is the prompt we want the user to see, and add a `while True:` loop here. Then we need to indent all of this inside the `while True:` loop to make it a block of code. And with those two simple changes, we now have our very first chatbot. We can type in `"hello"`, the bot's going to respond. If we type in `"buy"`, it'll say "Goodbye!". If we say something random, the bot's going to say "Sorry, I did not understand that.". It was that simple to create a chatbot in Python.
Moving on, it's time we talk about exceptions in Python, what to do when you encounter one, and how you can handle it properly. Because sometimes you're going to type in something weird, such as `print(whatever_that_is)`, and you're going to end up with an exception or an error, such as a `NameError`. Now, in recent versions of Python, you're going to get very descriptive error messages which help you understand what you did wrong. But of course, it would be nice to learn how to handle these exceptions because the one that we just encountered was caused by the developer. But there are going to be some that might be caused by the user. For example, imagine we have two variables `a` and `b`, and I'm going to be using the multiple assignment syntax, which means we can type in `a, b = 10, "15"`. And for whatever reason, let's pretend the user entered `"15"`. Now, if we were to do `a + b`, we're going to end up with an exception because you cannot add a string to an integer. It is an unsupported operand type: `int` and `str` just do not go together. But for whatever reason, that's what the user input. Now, if your user ever sees an exception message, it's probably a bad thing, and that can even lead them to uninstalling your app if it happens too frequently. Even if they're in the wrong, it's important to act as an adult when you are programming and to give the user a chance to fix their behavior. For example, instead of just printing `a + b`, what we're going to do is type in `try:`. Which means we're going to try this dangerous code. And if it doesn't work, we're going to `except Exception as e:`. And here we're going to print that "Something went wrong" and we're going to insert `e`, which is the error. Now, the next time we run this, we're not going to get an exception anymore, we're going to get an error message instead. Which means we can actually run more code under this `try` and `except` block. Here we can type in `print("Continuing with the program.")`. As you can see, when we run this, it's going to be able to continue with the program even if we encounter an exception. Without this, the program is just going to crash, and we're never going to reach the rest of the program.
So let's go back to what we had earlier. Here we can type in something else, such as `print("Please enter a valid number.")`. So that the next time the user inserts the text of `"15"` and tries to add it to 10, the exception is going to tell them exactly what they need to do to fix it. Anyway, that is the basic concept of handling an exception. Now, what I did here is considered a bad practice because `except Exception` handles all of the exceptions when what we really wanted to do is handle the `TypeError`. So as you can see, we can be much more specific with our exceptions. And here we can type in something such as `except TypeError: print("Please enter a number in the form of an integer or a float.")`. So now we're catching the correct error and giving them the correct message for that error. Which means that once they run the program and they add this silly input, it's going to ask them to "Please enter the number in the form of an integer or a float." Which means now we can change this to `10.5` or actually, to stay consistent, we'll just type in `15`, and it's going to work properly the next time they use that as an input. And one last thing to note is that you can add multiple `except` blocks. So you can actually handle all the other errors just by adding another `except` block: `except ValueError: print("Something else went wrong.")`. Because sometimes certain operations are going to lead to multiple errors. But once again, I never recommend using `except Exception as e` unless it's really just a last resort because this exception will absorb all of the errors. And one thing you need to learn in programming is that encountering errors and exceptions is not a bad thing when you are developing. In fact, you want to encounter as many as possible because this will lead to more consistent code when you're actually publishing your application. It's going to help you understand everything that can actually go wrong. And this approach just silently absorbs that error and makes it disappear. So once again, use this as a last resort.
Now, very quickly, I want to talk about imports in Python because sometimes you're going to want to import some external functionality into your script so that you can use it. For example, imagine you want to calculate the square root of a number. Now, personally, I'm no mathematician, so I prefer to use pre-made functionality to perform that calculation. And in Python, we can import a module called `math`. And what's good about this is that we can use a lot of its functionality for free just by importing it. And coincidentally, it has a square root function. So here we can calculate the square root of 3 using `math.sqrt(3)`. And once we run it, we're going to get the square root of 3. We can also import `math` using an alias. So for example: `import math as m`. Now we can `print(m.sqrt(4))`. And it's going to work exactly the same way, except we're using the alias this time. And finally, if you really want to be specific with your imports, you can import from `math` the `sqrt` function: `from math import sqrt`. And this time, we just type in `sqrt(5)` and it will work out of the box just by referring to the function name. And just so you know, with the third approach, you can add as many as you want. You can even add, let's say, `tan` which will return the tangent. So we can type in `tan(2)` and that will work just fine just by referring to the name.
Now, to end this crash course, we're going to be creating a simple project. And this is actually one of my favorite projects to make, and this is a chatbot, a very simple chatbot. So first, we're going to create a `bot_name: str = "Bob"`. Then the first message is going to be a print statement that says `print(f"Hello, I'm {bot_name}. How can I assist you today?")`. And once we see that message, we will start our `while True:` loop, which is an infinite loop. And the very first thing we want to do is take some user input, which will be of type string, and that's going to equal `input(">>> ")`. And since this returns a string, we're going to want to `.lower()` whatever the user enters. And the reason we're doing that is because if the user types in `"Hello"` with an uppercase H, and we're trying to compare that to `"hello"` with a lowercase H, this is going to return `False` because Python is case-sensitive, and a capital H and a lowercase H are two different things. Now, when you use the `.lower()` method on `"Hello"`, it turns all of the letters inside this string to lowercase, which makes it much easier to compare the two.
Anyway, `if user_input in ["hi", "hello"]:` then we will print that `print(f"{bot_name}: Hi there! How can I help you?")`. `elif user_input in ["bye", "cya"]:` we will print that `print(f"{bot_name}: Goodbye! Have a great day.")`. And as you can see here, I'm checking that the user input is inside this list of strings, which I find to be more convenient than checking for each one separately because it's nice to be able to understand multiple forms of input. But let's also add some functionality. `elif user_input in ["+", "add"]:` then let's make it so our bot can actually perform some mathematical operations. `print(f"{bot_name}: Sure, let's do some addition. Please enter two numbers.")`. And now comes the fun part. What we need to do here is try to first get the first number, which will be `num1: float`, and that's going to equal `float(input("First number: "))`. And as you can see, the code editor is telling us immediately that we got a string, but we were expecting a float. And thanks to this type annotation, we can fix that by surrounding this with the `float()` constructor. Then we're going to duplicate this and say `num2: float` and `float(input("Second number: "))`. And if that works, we're going to print the f-string with the bot name that says `print(f"{bot_name}: The sum is {num1 + num2}")`. And if it doesn't work, we're going to add the `except` block. And the main exception we can encounter here is the user adding or inputting a letter or some sort of symbol that is not a number, and that's going to give us a `ValueError`. So here we can print that `print(f"{bot_name}: Oops! That doesn't seem like a valid number. Try again.")`. Then we're just going to get out of this `except` block and go to the outermost layer where we have the `if` and we're going to add the `else` block. And this is going to cover all of the cases that we did not cover above. So `else: print(f"{bot_name}: I'm sorry, I don't understand that. Please try again.")`.
And in only 20 lines of code, we created our very first chatbot. So now it's actually time to test that it works. So here I'm going to run the script, and I'm probably going to make that bigger so we can see. And I'm just going to type in `"hi"`. As I mentioned earlier, the bot is going to be able to respond to that. Even if we have an uppercase H, it's going to understand that. We can type in `"cya"` and it doesn't understand that obviously because we did not code that, we only coded `"bye"` and `"cya"`. But if we type in `"bye"`, it'll be able to respond to that. But now let's try to add some numbers. So we'll type in `"add"`. We'll add 10 to 20, and the bot should give us the sum, which is 30. If we type in something random, the bot won't understand that. And if we try to get the sum using the plus, that's going to work too. But let's pretend we add something that doesn't work, such as `"oh"`. The bot is going to tell us immediately that it doesn't seem like a valid number. And instead of crashing our program, it's going to tell us immediately, which provides us with a much more smooth user experience. Anyway, I'm just going to say `"bye"`, and the bot will tell us "Goodbye! Have a great day."
So as you can see, it was a very simple chatbot that had some very simple functionality. But what's cool about this is that you can edit this as much as you like and you can add all sorts of functionality and so on. But yeah, that just about sums up the basics of Python. There's still a lot more to learn, but the best way to learn is to build apps. So decide on something you want to build and start coding it. As you try to build your app, you're going to have to start Googling to learn new things. That's all part of being a programmer. Even after 5 years of programming, I Google constantly. Although I recommend you start small, otherwise it might be a bit overwhelming. So search on how you can improve your chatbots, search on how you can scrape information from the internet. But don't try to build Facebook from day one. That's going to be incredibly overwhelming and it might even end with you giving up on programming because creating apps like Facebook isn't just one concept, but hundreds of different concepts combined.
Anyway, I hope you enjoyed this video. Do let me know in the comment section down below whether you have any other questions or whether a certain topic needed more explanation. But otherwise, with all that being said, as always, thanks for watching, and I'll see you in the next video.