You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
465 lines
39 KiB
465 lines
39 KiB
<!doctype html> |
|
<html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|
<title>My Learning Website</title> |
|
<link href="/styles/styles.css" rel="stylesheet" type="text/css"> |
|
<link href="/programming/styles/styles.css" rel="stylesheet" type="text/css"> |
|
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> |
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// --> |
|
<!--[if lt IE 9]> |
|
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> |
|
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> |
|
<![endif]--> |
|
</head> |
|
<body> |
|
|
|
<div class="banner"> |
|
<h1 class="courselink">Python Essential Training</h1> |
|
<h2 class="lecturer">LinkedIn Learning : Bill Weinman</h2> |
|
<h2 class="episodetitle">Language Overview</h2> |
|
</div> |
|
|
|
<article> |
|
<h2 class="sectiontitle">Hello world</h2> |
|
<p>This is just a quick overview of the Python language so it will introduce a lot of concepts such as loops and functions which we will examine in their own individual chapters later in the course.</p> |
|
<p>A typical Python program will look something like this.</p> |
|
<pre class="inset"> |
|
#!/usr/bin/env python3 |
|
# Copyright 2009-2017 BHG http://bw.org/ |
|
|
|
print('Hello, World.')</pre> |
|
<p>The first line is the shebang line. Note that in this case, we are using env to automatically locate the python3 interpreter rather than specifying the actual path to locate it.</p> |
|
<p>The last line calls the print function, and remember that unlike Python 2, print is a function in Python 3 so we have an argument list of parameters in parentheses. In this case, the only argument is the string to be printed.</p> |
|
<h2 class="sectiontitle">Python Anatomy</h2> |
|
<p>Python provides facilities similar to C or Java for printing formatted strings. Consider the following code example.</p> |
|
<pre class="inset"> |
|
#!/usr/bin/env python3 |
|
# Copyright 2009-2017 BHG http://bw.org/ |
|
|
|
import platform |
|
|
|
print('This is python version {}'.format(platform.python_version()))</pre> |
|
<p>As I mentioned earlier, print is a function so what we are seeing here in parentheses is the argument passed to that function and the argument is an expression. We have a string followed by the format method. This is a string method and it returns the version number of python. This version number is added to the string in place of the placeholder, {}.</p> |
|
<h2 class="sectiontitle">Expressions and Statements</h2> |
|
<p>The difference between statements and expressions can vary from language to language, but in general terms</p> |
|
<pre class="inset"> |
|
• Expression - an expression is a unit of evaluation |
|
• Statement - a statement is a unit of execution</pre> |
|
<p>Anything that returns a value is an expression and that includes assignments in Python but it can also be a literal. The following are all considered to be expressions in Python.</p> |
|
<pre class="inset"> |
|
• x = y - an assignment |
|
• x * y - an operator |
|
• (x, y) - an aggregate value, in this case a tuple |
|
• x - a simple value |
|
• True - a built-in constant value |
|
• f() - a function</pre> |
|
<p>Note that a function is always considered to be an expression because it always returns a value but the value can sometimes be none.</p> |
|
<p>A statement is a more generic thing but essentially it is just any self-contained line of executable code and it includes expressions (so an expression is a statement that returns a value).</p> |
|
<p>Let's look at another example</p> |
|
<pre class="inset"> |
|
#!/usr/bin/env python3 |
|
# Copyright 2009-2017 BHG http://bw.org/ |
|
|
|
import platform |
|
|
|
version = platform.python_version() |
|
|
|
print('This is python version {}'.format(version))</pre> |
|
<p>In this example, we have three statements, an import statement, an assignment and a print statement. To explain the difference between a statement and an expression, consider the line</p> |
|
<pre class="inset"> |
|
version = platform.python_version()</pre> |
|
<p>Think about whether this is an expression or a statement and you may conclude that it is not an expression, it's a statement. The right hand side of the assignment</p> |
|
<pre class="inset"> |
|
platform.python_version()</pre> |
|
<p>is an expression because it returns a value which is referenced by the variable version. In fact, one possible way to distinguish an expression is whether you can assign it to something as we did when assigning the value returned by this expression to version. But the statement also includes the variable name so does this return a value? Let's check that by another couple of lines of code.</p> |
|
<pre class="inset"> |
|
variable2 = version = (platform.python_version()) |
|
|
|
print(variable2)</pre> |
|
<p>The output we get from this is</p> |
|
<pre class="inset"> |
|
This is python version 3.9.9 |
|
3.9.9</pre> |
|
<p>This confirms that an assignment is an expression that returns the same value that has been assigned to the variable, so in the original example, the expression was</p> |
|
<pre class="inset"> |
|
platform.python_version()</pre> |
|
<p>and this returned a value of 3.9.9 and this value was assigned to version. In the second example, the expression is</p> |
|
<pre class="inset"> |
|
version = platform.python_version()</pre> |
|
<p>which also returns a value of 3.9.9 which was, this time, assigned to variable2 and we confirmed this by printing out the value of variable2.</p> |
|
<p>What about the print statement, is that an expression too? Again, we can test that by seeing if we can assign the value returned by it to a variable.</p> |
|
<pre class="inset"> |
|
print_var= print('This is python version {}'.format(version))</pre> |
|
<p>If we try to print the value of print_var, the output is none. Remember that a function always returns a value, but this value can sometimes be none so in this case, the print function returns none which we assign to print_var which means this is an expression, albeit an expression that returns a value of none.</p> |
|
<p>The only other statement we have is</p> |
|
<pre class="inset"> |
|
import platform</pre> |
|
<p>Common sense will probably tell you this is not an expression and in fact, if we try to assign its returned value to a variable like this.</p> |
|
<pre class="inset"> |
|
platform_var = import platform</pre> |
|
<p>We get an invalid syntax error because we are trying to assign a value to a variable using a statement that does not return a value so it's not an expression.</p> |
|
<p>Since Python generally follows a convention of one statement per line, it doesn't require a terminator but you can use a semi-colon to separate statements on the same line. This is considered to be poor practice in Python so you won't see it very often.</p> |
|
<h2 class="sectiontitle">Whitespace and Comments</h2> |
|
<p>In some cases, white space is ignored in Python just as it is in other languages but it can be significant. In particular, it is used to denote code blocks in the same way that curly braces are used in C or Java. We can see an example of that here.</p> |
|
<pre class="inset"> |
|
#!/usr/bin/env python3 |
|
# Copyright 2009-2017 BHG http://bw.org/ |
|
|
|
import platform |
|
|
|
def main(): |
|
message() |
|
|
|
def message(): |
|
print('This is python version {}'.format(platform.python_version())) |
|
|
|
if __name__ == '__main__': main()</pre> |
|
<p>There are two functions, main and message and each has a code block associated with it. If we look at the main function for example, the next line is indented which indicates that this is part of the main function. The next line after that is the start of the message function and this is not indented so it is not part of the main function.</p> |
|
<p>The blank lines don't have any special significance. If we write the code like this</p> |
|
<pre class="inset"> |
|
#!/usr/bin/env python3 |
|
# Copyright 2009-2017 BHG http://bw.org/ |
|
|
|
import platform |
|
|
|
def main(): |
|
|
|
message() |
|
def message(): |
|
print('This is python version {}'.format(platform.python_version())) |
|
|
|
if __name__ == '__main__': main(</pre> |
|
<p>it would work in exactly the same way. so white space in the form of blank lines are ignored by the Python interpreter.</p> |
|
<p>We can have different levels of indentation but this denotes different blocks of code - nested blocks. All statements belonging to the same block of code must be indented to the same level. The degree of indentation is unimportant as long as this rule is followed. Let's look at another, slightly more complex example.</p> |
|
<pre class="inset"> |
|
def message(): |
|
print('This is python version {}'.format(platform.python_version())) |
|
print('line 2') |
|
if True: |
|
print('line 3') |
|
else: |
|
print('not true')</pre> |
|
<p>Only the message function is shown here but as in the previous example, it is called from the main function. The function contains a block of code made up of four statements but this includes an if statement and there is a block of code associated with that. We also have an else clause which also has a single statement associated with it. We can see this from the indentation. As a matter of interest, when we run this code, the output is</p> |
|
<pre class="inset"> |
|
This is python version 3.9.9 |
|
line 2 |
|
line 3</pre> |
|
<p>When the function is called, the first print statement is executed, then the second print statement. Next comes the if statement and this is a pretty straightforward example. True is always true so we are not really evaluating a condition here (technically we are but this is really just a mechanism to show the if statement working) and therefore the code block associated with the if statement is executed and the code block associated with the else block is not. We could change this to</p> |
|
<pre class="inset"> |
|
if False:</pre> |
|
<p>Similarly, this will always be false so the code associated with the else clause would be executed.</p> |
|
<p>A comment in Python starts with a # and ends at the end of the line, so these are inline comments. There are no block comments.</p> |
|
<h2 class="sectiontitle">Using print()</h2> |
|
<p>We mentioned earlier that print is a function in Python 3 so it will take 0 or more arguments. In it's simplest form, it can be used to output a string literal.</p> |
|
<pre class="inset"> |
|
print(''Hello world!')</pre> |
|
<p>If we want to add a variable, for example we might want to print the same string followed by a variable referenced by x. To do this, we put a placeholder in the string where we want the variable to appear. In Python, the placeholder is a pair of curly braces. We then apply the string method, format to that string and pass the variable as an argument to format which Python puts in the string in place of the placeholder.</p> |
|
<pre class="inset"> |
|
print(''Hello world! {}'.format(x))</pre> |
|
<p>We can use this method to insert multiple variables by inserting a placeholder for each variable, and passing the variables as a comma separated list to format.</p> |
|
<pre class="inset"> |
|
print('Hello, World. {}, {}'.format(x, y))</pre> |
|
<p>One consequence of the fact that format is a string method rather than a print method is that we can use it to build a string which is assigned to a variable which we can then send to the print function. So</p> |
|
<pre class="inset"> |
|
s = 'Hello, World. {}, {}'.format(x, y) |
|
print(s)</pre> |
|
<p>will do exactly the same thing as the previous code example.</p> |
|
<p>Now, remember that in Python 2, print is not a function and a string is not an object, so this method wouldn't work. Instead, a method that is more C-like was used. It still uses a placeholder but this is % followed by a value indicating the type of the variable, for instance %d for integer variables. This is followed by a % sign and the variable name.</p> |
|
<pre class="inset"> |
|
print ('Hello World! %d, %d' % x % y)</pre> |
|
<p>Since this is an older method, you will most likely see it only in Python 2 (or earlier) code. In Python 3 code, you should always use the format method. In any case, it is likely to disappear from Python altogether at some point.</p> |
|
<p>Python 3.6 introduced a more condensed version of the format which is called an f string. In the print argument list, we put an f at the front so we don't need to explicitly specify the format method or worry about providing its arguments.</p> |
|
<pre class="inset"> |
|
print (f'Hello World! {x}, {y}')</pre> |
|
<p>You can also do this.</p> |
|
<pre class="inset"> |
|
print (f'Hello World! {x, y}')</pre> |
|
<p>and this does work, but not quite in the same way. This seems to indicate to Python the fact that we want to group these variables together so it outputs them as a set or a tuple like this.</p> |
|
<pre class="inset"> |
|
Hello World! (42, 84)</pre> |
|
<h2 class="sectiontitle">Blocks and Scope</h2> |
|
<p>In general, the number of characters by which you indent your code is irrelevant. You might just think of this as levels so let's assume for the moment that your first line of code has no indentation, that gives you level 1. Any line that follows is going to be an individual line of code if its not indented (if it has level 1 indentation.</p> |
|
<p>Let's say that the next line of code is indented by four characters, that becomes level two and if the next is indented by 10 characters, that becomes level 3 and so on. Any line of code indented to level 2 is a block of code belonging to the last line before it that is indented to level 1. Similarly, any line of code indented to level 3 is a block of code belonging to the last line before it that is indented to level 2.</p> |
|
<p>The end of the code is determined by the first line of code indented at a lower level. For example, let's say we have 4 lines of code and first 3 are indented, respectively, by 0, 4 and 10 characters so these are levels 1, 2 and 3. What options are available for the fourth line?</p> |
|
<pre class="inset"> |
|
• We can indent it by 10 characters (level 3) so lines 3 and 4 belong to the same block of code. |
|
• We can indent it by more than 10 characters giving us a fourth level of indentation. This can be any number of characters greater than 10. |
|
• We can indent it by less than 10 characters. Here, are options are more limited since we can only go back to level 2 or level 1 so indentation must be by 0 or 4 characters.</pre> |
|
<p>Consider this example.</p> |
|
<pre class="inset"> |
|
if x < y: |
|
print('x < y: x is {} and y is {}'.format(x, y)) |
|
print('Hello!')</pre> |
|
<p>The first line is level 1, the second is level 2. The third line is somewhere between level 1 and level 2 and as a result we get an error.</p> |
|
<pre class="inset">IndentationError: unexpected indent</pre> |
|
<p>Let's look at another example.</p> |
|
<pre class="inset"> |
|
x = 42 |
|
y = 73</pre> |
|
<p>This looks like it follows the rules we described earlier, with the first line of code being level 1 and the second being level 2. However, this also gives us an indentation error. This might seem puzzling if you look at it from a Python indentation perspective, but it should make perfect sense if you think about it from a programming perspective. The second line of code doesn't depend in any way on the first line of code so it doesn't make sense to treat it as a dependent block of code. Compare this with the following example.</p> |
|
<pre class="inset"> |
|
if x < y: |
|
print('x < y: x is {} and y is {}'.format(x, y))</pre> |
|
<p>The indented line of code is executed or not executed depending on the result of evaluating the if condition, so it needs to be identified as a block of code associated with the if statement and so indentation is both expected and sensible. This would also work.</p> |
|
<pre class="inset"> |
|
if x < y: |
|
print('x < y: x is {} and y is {}'.format(x, y))</pre> |
|
<p>but it doesn't do the same thing. In this example, there is no block of code associated with the if statement so this is evaluated and will return either true or false. The print statement, however, will be executed regardless because it no longer depends on the if statement. So basically, use indentation to create code blocks when the code in the block depends on some other statement (such as an if statement or a loop).</p> |
|
<p>It is interesting, and perhaps surprising, to note that blocks do not define variable scope so if you define a variable inside a block, you can also reference outside the block, in general. However, there are other mechanisms that do define scope and these are functions, objects and modules. Assuming your code doesn't use any of these, the variable will be accessible to any part of the code once it has been declared and perhaps initialised. If you have, for example, a function, then the same is true inside the function so a variable declared within a code block is going to be available outside of the code block, but not outside of the function.</p> |
|
<h2 class="sectiontitle">Conditionals</h2> |
|
<p>Conditional statements in Python are similar to languages such as C or Java, but it uses a colon to terminate the condition as we saw in the earlier example and it is usually followed by a code block. This is, strictly speaking not required, but if there is no code block, the if statement won't do anything. There is an exception to this rule (again, this is similar to Java and C) and that is where a statement appears on the same line as the if statement.</p> |
|
<pre class="inset"> |
|
if x < y: print('x < y: x is {} and y is {}'.format(x, y))</pre> |
|
<p>This style is discouraged in Python. It is generally considered better practice to put any statements associated with a conditional in an indented code block, even if it is just a single statement. If there is more than one statement associated with the conditional, you have to use a code block.</p> |
|
<p>You can also add an else clause as we saw earlier which acts as a kind of default case where some code is executed if the previous conditional or conditionals did not trigger a code block. An else clause can also add another conditional statement, making it an else if clause which in Python uses the elif keyword. Putting all of this together, let's say we have some variable, x, and we want to print out something that tells us whether x is more than or less than 5, so this gives us three possible outcomes.</p> |
|
<p>We might use an if statement to check whether it is less than 5, an elif statement to check whether it is more than 5 and an else statement for the default case, which in this example would be x = 5. The code would look something like this.</p> |
|
<pre class="inset"> |
|
#!/usr/bin/env python3 |
|
# |
|
# Author - Philip Osztromok |
|
# 9 December 2021 |
|
# |
|
x = 5 |
|
|
|
if (x < 5): |
|
print (f'x is less than 5') |
|
elif (x > 5): |
|
print(f'x is more than 5') |
|
else: |
|
print(f'x is 5')</pre> |
|
<p>That's a very simple example, but it does give us the basic structure for using an if statement with optional elif and else clauses. If you put all of these together, this gives you a cohesive code group. That is, both the elif and else clauses are related to the original if statement. Consider this example.</p> |
|
<pre class="inset"> |
|
#!/usr/bin/env python3 |
|
# |
|
# Author - Philip Osztromok |
|
# 9 December 2021 |
|
# |
|
x = 3 |
|
|
|
if (x < 5): |
|
print (f'x is less than 5') |
|
if (x > 5): |
|
print(f'x is more than 5') |
|
else: |
|
print(f'x is 5')</pre> |
|
<p>This is similar, but the first if statement is not related to any other statement, so although it looks like it does the same thing as the previous example and in some cases, will give the same results, it is slightly different. In this case, we gave x a value of 3 so the first if statement will return a true value and its associated code block will be executed.</p> |
|
<p>The second if statement is then evaluated and will return a false value since x is not greater than 5 but it will then execute the statement associated with the else clause so the output will be.</p> |
|
<pre class="inset"> |
|
x is less than 5 |
|
x is 5</pre> |
|
<p>So this is something to be careful with. Using consecutive conditional statements like this may be correct for your code, but if you want the second (or subsequent) conditional to execute or not based on the result of evaluating the first, you will want to tie them together by using if and then elif statements.</p> |
|
<p>You can string any number of elif commands together (after an if command) and this can give you the equivalent of a switch or case statement. Python, in fact, doesn't have switch or case statements so if you want to code something like that in Python, you will probably want to use elif. You could also use a sequence of if statements but this is only going to work if there is no default code to execute. That is, the conditional statements must be self-contained so each and every one will execute some code depending on the result of evaluating the condition and will not depend on the results of the other statements. Let's look at a very quick example of that using only if statements.</p> |
|
<pre class="inset"> |
|
#!/usr/bin/env python3 |
|
# |
|
# Author - Philip Osztromok |
|
# 9 December 2021 |
|
|
|
x = 0 |
|
|
|
if (x==1): |
|
print (f"Menu option {x} selected.") |
|
if (x==2): |
|
print (f"Menu option {x} selected.") |
|
if (x==3): |
|
print (f"Menu option {x} selected.") |
|
if (x==4): |
|
print (f"Menu option {x} selected.") |
|
if (x==5): |
|
print (f"Menu option {x} selected.") |
|
if (x < 1 or x > 5): |
|
print("Please select a number between 1 and 5")</pre> |
|
<p>This is a simple example that you might see in code implementing a menu where each option calls some function to run the code corresponding to that option and this is something where you would probably use a switch statement in C or Java. Note that this syntax means that you have to specifically code a conditional for exceptional values of x (that is, where the value does not correspond to one of the expected values which are any number between 1 and 5. Let's see the same code example using elif statements.</p> |
|
<pre class="inset"> |
|
#!/usr/bin/env python3 |
|
# |
|
# Author - Philip Osztromok |
|
# 9 December 2021 |
|
|
|
x = 3 |
|
|
|
if (x==1): |
|
print (f"Menu option {x} selected.") |
|
elif (x==2): |
|
print (f"Menu option {x} selected.") |
|
elif (x==3): |
|
print (f"Menu option {x} selected.") |
|
elif (x==4): |
|
print (f"Menu option {x} selected.") |
|
elif (x==5): |
|
print (f"Menu option {x} selected.") |
|
else: |
|
print("Please select a number between 1 and 5")</pre> |
|
<h2 class="sectiontitle">Loops</h2> |
|
<p>We saw that with the if statement, Perl has a syntax that will look slightly strange to developers with a background in languages such as C or Java. It also use a similar syntax for loops and, of course, follows the same rules where a block of code is denoted by the indentation. The following example demonstrates the syntax for a while loop.</p> |
|
<pre class="inset"> |
|
#!/usr/bin/env python3 |
|
# Copyright 2009-2017 BHG http://bw.org/ |
|
|
|
words = ['one', 'two', 'three', 'four', 'five'] |
|
|
|
n = 0 |
|
while(n < 5): |
|
print(words[n]) |
|
n += 1</pre> |
|
<p>We have an array with five string elements (index values start at 0 so they run from 0 to 4) and a variable, n, which we initialise with a value of 0. Inside the while loop, we use the value of n to reference an element from the array. The value of n is incremented and the loop moves onto the next iteration and it stops when n reaches a value of 5 (more specifically, the loop will continue to iterate while the value of n is less than 5.)</p> |
|
<p>Python doesn't have a do while loop, which can be a useful construct where you have a block of code that you want to execute until a specified condition is met, but where you also need to ensure is executed at least once. An example of this is where you want the user to input a password and you want the code for this to repeat until the correct password has been entered.</p> |
|
<p>A do while loop would be ideal, but you can simulate this behaviour in Python by specifying a condition that gives you an infinite while loop (that is, a loop where the condition always evaluates to true). You can then evaluate the condition that will terminate the loop inside each iteration and jump out of the loop with the break command when the condition is met.</p> |
|
<p>Let's say that we have a variable called password which has a value of "password". Inside the while loop, the user inputs a string in each iteration and the loop stops when this string matches some pre-set value. Obviously in a real-world application, the users password would be retrieved from a database and the user input would be compared to it. The code would look like this.</p> |
|
<pre class="inset"> |
|
#!/usr/bin/env python3 |
|
# |
|
# Author - Philip Osztromok |
|
# 9 December 2021 |
|
|
|
password = "password" |
|
|
|
while True: |
|
pw=input("Please enter your password: ") |
|
if pw == "password": |
|
break |
|
print ("Incorrect password, please try again") |
|
print("Password accepted")</pre> |
|
<p>Notice that there are no conditions associated with either of the print statements. Inside the loop, we have the statement</p> |
|
<pre class="inset"> |
|
print ("Incorrect password, please try again")</pre> |
|
<p>Since this comes after the if statement that checks the password and ends the loop if it is correct, whenever the password is incorrect, we don't break out of the loop and so the print statement is executed. If the password is correct, we break out of the loop before the print statement is executed.</p> |
|
<p>The second print statement</p> |
|
<pre class="inset"> |
|
print("Password accepted")</pre> |
|
<p>is only executed after the loop terminates and since the loop only executes when the correct password has been entered, we don't need to check it again to confirm that it is correct.</p> |
|
<p>Something to be wary of is that this type of syntax involves creating an infinite loop which is generally considered to be a bad thing so you need to be aware of the fact that if the specified condition cannot be met, it may not be possible to break out of the loop at all so you may want to add some code to counter that. For example, you might add a counter for the number of incorrect attempts that also breaks out of the loop if the counter reaches three, for example.</p> |
|
<p>A for loop is also a little bit different. A typical loop might look something like this.</p> |
|
<pre class="inset"> |
|
#!/usr/bin/env python3 |
|
# Copyright 2009-2017 BHG http://bw.org/ |
|
|
|
words = ['one', 'two', 'three', 'four', 'five'] |
|
|
|
for i in words: |
|
print(i)</pre> |
|
<p>This example is a little bit like a for each found in some programming languages. We have a collection of items and the loop iterates once for each element in that collection. The i in the for loop acts a little bit like an index and it is automatically incremented on each iteration and. However, it is not quite an index, if it were, we would print words[i] for each iteration and this is what we would see in a C or Java element. In this case,</p> |
|
<pre class="inset"> |
|
for i in words</pre> |
|
<p>essentially means that i represents each element in turn so in the first iteration, where i represents the first element or</p> |
|
<pre class="inset"> |
|
words[0]</pre> |
|
<p>the print statement</p> |
|
<pre class="inset"> |
|
print(i)</pre> |
|
<p>outputs the element itself. The result of running this code is therefore to output each element of the array in turn. This form of the for loop is very convenient for iterating through a collection such as an array so you will see it used quite a lot. Python doesn't have a for loop that looks like a traditional C loop where you use a counter to iterate for a fixed number of times, but it does have its own syntax to do the same thing.</p> |
|
<p>For example, let's say we want to compute a factorial so we will take a number, let's call that n for now, and we will want to run a for loop that executes n + 1 times. We will initialise our factorial with a value of 1 and then for each iteration of the loop, we will multiply the factorial by the index value so the loop is going to look something like this.</p> |
|
<pre class="inset"> |
|
#!/usr/bin/env python3 |
|
# Copyright 2009-2017 BHG http://bw.org/ |
|
|
|
f = 1 |
|
n = 10; |
|
|
|
for x in range(1, n+1): |
|
f = f * x |
|
print(f"x = {x}, f = {f}") |
|
print(f"Factorial of {n} is {f}")</pre> |
|
<p>The interesting part of this is the for loop which is controlled by the line</p> |
|
<pre class="inset"> |
|
for x in range(1, n+1):</pre> |
|
<p>Let's compare this to a for loop in C where the control line will be something like this.</p> |
|
<pre class="inset"> |
|
for (x = 1, x <=10, x++) {}</pre> |
|
<p>The Python for loop specifies the first two parts of the C loop as the range so this gives us the starting value of 1 and the ending value of 10. Actually, with the Python loop, the end value specified seems to be the first value that is not included in the loop - that is, when the value of the counter reaches the specified value, the loop terminates and that is why the upper bound of the loop is n + 1. An alternative would be to specify n as the number after the target for the factorial. For factorial 10, that would give us a value of 11. Bear in mind that a for loop can count up from zero so it makes sense that counting from 1 to n will iterate n - 1 times since you skipped 0.</p> |
|
<p>You can specify a for loop in Python with the upper boundary only like this</p> |
|
<pre class="inset"> |
|
for x in range(6)</pre> |
|
<p>and this will loop 6 times but the loop counter will run from 0 so the values over which the loop will iterate are actually 0 to 5. We could use this type of syntax for our factorial like this</p> |
|
<pre class="inset"> |
|
for x in range (n)</pre> |
|
<p>This will iterate for values from 0 to 9 and you might be tempted to think that we could write our loop like this</p> |
|
<pre class="inset"> |
|
for x in range(n+1)</pre> |
|
<p>which will iterate over the values from 0 to 10. However, this wouldn't work for our factorial because the first iteration would give a result for f of 0 so any number you subsequently multiply it by will give you a result of 0 so another option would be to use the loop in this form but add 1 to it every time.</p> |
|
<pre class="inset"> |
|
#!/usr/bin/env python3 |
|
# Copyright 2009-2017 BHG http://bw.org/ |
|
|
|
f = 1 |
|
n = 10; |
|
|
|
for x in range(n): |
|
f = f * (x+1) |
|
print(f"x = {x}, f = {f}") |
|
print(f"Factorial of {n} is {f}")</pre> |
|
<p>This gives exactly the same result so there are several ways in which you can code the loop for something like this. In my opinion, the best way is the syntax that makes the intention of the code clearer. In this example, you want it to be clear that you are iterating over the numbers from 1 to 10 and you can be explicit with this in C with a loop control like this</p> |
|
<pre class="inset"> |
|
for (x = 1; x <= 10; x++) {}</pre> |
|
<p>From what I know of for loops in Python, it is not possible to be completely explicit in the same way since we need to either count from 0 to n and add 1 to the value each time or count from 1 to n+1 so you may well want to add a comment to the loop to clarify what values you are iterating and why you have used these particular values in the loop. Personally, I think that this makes Python more susceptible to out by one errors in a for loop than would be the case in C but it is possible that Python has a better form of the syntax that I am simply not aware of yet.</p> |
|
<p>One other thing about Python for loops that may be worth mentioning is the fact that the increment is not specified so the loop counter always increments by one for each iteration. There is no step keyword that you can use in a for loop, but it is possible to implement this using a range that specified both upper and lower boundaries. For instance, let's say we want to output all of the even numbers from 1 to 10, we could do that using a range that starts at 2 and counts up to 11 in steps of 2 like this (bear in mind that in this example, n still has a value of 10).</p> |
|
<pre class="inset"> |
|
for x in range(2, n+1, 2): |
|
print(x)</pre> |
|
<p>So this is the equivalent of increasing the value of the counter by 2 for each iteration.</p> |
|
<h2 class="sectiontitle">Functions</h2> |
|
<p>Functions in Python are quite similar to C or Java, the main difference being that they are introduced with the def keyword. This is followed by the name of the function and an argument list in parentheses. This must always be present, even if it is empty. Following that, we have the code block associated with the function.</p> |
|
<p>Remember that a function always returns a value in Python, even if that value is none. For this reason, you are not required to specify a return value which would mean that you have an implicit return value of none. If you want to do explicitly return something, you would use the return keyword.</p> |
|
<pre class="inset"> |
|
return 1</pre> |
|
<p>To call the function, you just need its name followed by the list of arguments you want to pass to it.</p> |
|
<pre class="inset"> |
|
function(47)</pre> |
|
<p>In this case, the function is expecting a single value. This highlights another thing that is different between functions in Python and functions in C. Python seems to use Duck typing when it comes to identifying data types. This also applies with the arguments to a function in Python. You may have noticed that the function definition in the above example takes n as an argument but doesn't specify the type. This is because the arguments to a function in Python are dynamically-typed. That is, the type is determined when the code is running and a call to the function is made. If you pass it a number, it will print out a number, if you pass it a string, it will printout a string and so on.</p> |
|
<p>The number of arguments you pass to it must equal the number of arguments it expects (there is an exception to this rule which I will explain in a moment). In this example, if we don't pass it any argument, we will get an error like this.</p> |
|
<pre class="inset"> |
|
TypeError: function() missing 1 required positional argument: 'n'</pre> |
|
<p>If we pass it too many arguments, we will get an error like this.</p> |
|
<pre class="inset"> |
|
TypeError: function() takes 1 positional argument but 2 were given</pre> |
|
<p>We can give a function argument a default value like this.</p> |
|
<pre class="inset"> |
|
def function(n=1):</pre> |
|
<p>In this case, if we call the function without any arguments, n will have a value of 1 so we won't get any error.</p> |
|
<p>One other thing we need to be aware when writing functions in Python is that you must define the function before calling it so you will often see this type coding style where the function definitions appear first followed by the code that uses those functions.</p> |
|
<p>I have added a sample file with some more complex functions to give you a better example of what Python functions look like and you can see this in <a href="samples/Ch02/list_primes.html" target="_blank">list_primes.html</a>. Here, we have two functions. One that takes a single numerical argument and will print out a confirmation of whether that number is prime or not. The second function doesn't take any arguments, but it outputs a list of prime numbers less than 100.</p> |
|
<p>The most interesting feature of the second function is the print statement</p> |
|
<pre class="inset"> |
|
print(n, end=' ', flush=True)</pre> |
|
<p>which is more complex than previous print statements we have seen. It takes three arguments as follows.</p> |
|
<pre class="inset"> |
|
• n - this is simply the variable which represents a prime number. Note that the value of n is not necessarily prime, but the print statement only executes when it is prime. |
|
• end=" " - this seems to add a space at the end of the line without generating a new line character so it leads to a list of numbers on a single line that are separated by spaces. Print itself seems to generate a newline so I guess that this is creating a new end of line character which is just a space rather than the newline. |
|
• flush="True" - this flushes the output buffer. We will see more about how this works later.</pre> |
|
<h2 class="sectiontitle">Objects</h2> |
|
<p>Python provides a mechanism for defining a class and this can contain both methods and properties, but properties has a specific meaning in Python so you will often hear a different term used for these. In the course, the term class variables is used although instance variables might be better. There is a sample of some code used to define a class called Duck with two methods called quack and walk in <a href="samples/Ch02/duck.html" target="_blank">duck.html</a>.</p> |
|
<p>The class is defined using the keyword class followed by the name of the class and a colon. In common with most languages that allow the definition of classes, the class name starts with an upper case letter. Inside the class, methods are defined in the same way that we saw previously for functions.</p> |
|
<p>The first argument in a class method is always self, which is a reference to the object itself. Actually, calling this self is a convention, you can give it some other name if you like but your code will be easier for others to understand if you follow the convention.</p> |
|
<p>The general usage is fairly similar to other programming languages. We create an instance of the class by invoking the class name without needing to use the keyword, new.</p> |
|
<pre class="inset"> |
|
donald = Duck()</pre> |
|
<p>To invoke a class method, we use a dot notation to send a message to the class instance.</p> |
|
<pre class="inset"> |
|
donald.quack() |
|
donald.walk()</pre> |
|
<p>We didn't use any class variables here (properties) but these are added in the same way in which you would add variables to a function. For example, we could re-write the code in duck.html to use a couple of string variables so that the quack and walk methods can access these class variables rather than print string literals. The code for this is in <a href="samples/Ch02/duck2.html" target="_blank">duck2.html</a>.</p> |
|
<p>One final point to make about these examples is that they both create a function called main and then called the function, rather than having code that is independent of any function that is called when the code runs, other than the call to main. This type of program structure where the code is packaged within a function called main and the only code not inside a function is the call to main is actually quite common in Python and we will see this again in future examples.</p> |
|
</article> |
|
|
|
<div class="btngroup"> |
|
<button class="button" onclick="window.location.href='introduction.html';"> |
|
Previous Chapter - Introduction and Installation |
|
</button> |
|
<button class="button" onclick="window.location.href='types.html';"> |
|
Next Chapter - Types and Values |
|
</button> |
|
<button class="button" onclick="window.location.href='pythonessentialtraining.html'"> |
|
Course Contents |
|
</button> |
|
<button class="button" onclick="window.location.href='/programming/programming.html'"> |
|
Programming Page |
|
</button> |
|
<button class="button" onclick="window.location.href='/index.html'"> |
|
Home |
|
</button> |
|
</div> |
|
</body> |
|
</html> |