├── site ├── favicon.gif ├── favicon.ico ├── cover.jpg ├── section │ ├── c15.html │ ├── about.html │ ├── default.html │ ├── c1.html │ ├── c2.html │ ├── c13.html │ ├── c11.html │ ├── c10.html │ ├── c4.html │ ├── c3.html │ └── c7.html └── index.php ├── README.md └── LICENSE /site/favicon.gif: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/scotchfield/python-book/HEAD/site/cover.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | python-book 2 | =========== 3 | 4 | Learn Python, Break Python book source 5 | 6 | --- 7 | 8 | This is the source code for http://learnpythonbreakpython.com, the online 9 | home of Learn Python, Break Python. 10 | 11 | http://www.amazon.com/Learn-Python-Break-Beginners-Programming-ebook/dp/B00IGF3E36/ 12 | 13 | --- 14 | 15 | Please feel free to contribute! If you catch a problem, submit pull 16 | requests or issues, and they'll be used to update future versions. 17 | 18 | Thanks! 19 | -------------------------------------------------------------------------------- /site/section/c15.html: -------------------------------------------------------------------------------- 1 |
Congratulations, you're a Python programmer! You've started from scratch, perhaps with no programming experience at all, and are now speaking in terms of classes, modules, function references, and all kinds of other wonderful and geeky terms. You have the ability to open up a text window and to take charge of your computer in a way that most people perceive as pure magic. You can write complicated programs that perform data analysis, verify homework problems, or even play games. Great work!
4 | 5 |The challenge doesn't end here though. This is not a comprehensive list of Python functions, and there isn't enough space to go through other modules or applications that you might attempt to tackle. Your path from here is your own. If you'd like to continue programming, and I certainly hope that you do, do some brainstorming and come up with programs that you'd like to write. If you're a gamer, write a text adventure game. If you come from a finance background, start designing a tool that can help you crunch numbers in an effective way. If you feel like automating parts of your career or your life will give you more time or money, start writing those tools!
6 | 7 |It might sound cheesy when I say this, but there really isn't any end to the types of applications that you're able to create in a programming language. Even the programming language itself was written by somebody, right? Use the experience that you've gained from working through this material to start working on the things that you want to write. Programming is a very fulfilling activity. Let your creativity go wild, and see what kind of programs you come up with.
8 | 9 |Best of luck!
10 | 11 |Alexander
12 | -------------------------------------------------------------------------------- /site/section/about.html: -------------------------------------------------------------------------------- 1 |Learn Python, Break Python is a hands-on introduction to the Python programming language, written for people who have no experience with programming whatsoever. Hey, we all have to start somewhere. As such, the examples and teaching style used in this text make absolutely no expectations about your prior programming experience.
4 | 5 |If you've never used a programming language before, leaping into Python might seem a bit scary at first. You don't need to worry. Learning how to program a computer is far from impossible. Anyone can pick up the art of programming with a little time and a bit of patience.
6 | 7 |However, when learning something new, I try to break things. In fact, in many cases, I go out of my way to break stuff. When picking up a new concept like computer programming, you can actually increase your comfort level by figuring out the type of cases that are likely to break. You'll see what data can be used and where, and when you inevitably run into errors later (like everyone does), you won't be surprised.
10 | 11 |The idea that breaking things can actually help you become a better programmer is a central idea in this book, and I hope that you take full advantage. I've broken a lot of code in my day, whether intentionally or not, and I think that it's given me the knowledge to help teach other people how to write good code.
12 | 13 |Learn Python, Break Python starts with a gentle introduction to programming. Slowly, through examples and exercises, we build up to a level of comfort by introducing more complicated program elements, and show where they can be used and how we can break them. By building up knowledge in this way, we hope to impart a level of comfort that will make you comfortable trying new things and taking risks; in short, we want you to be comfortable with programming.
16 | -------------------------------------------------------------------------------- /site/section/default.html: -------------------------------------------------------------------------------- 1 |
3 | Learn Python, Break Python is a hands-on introduction to the Python programming language, written for people who have no experience with programming whatsoever. Hey, we all have to start somewhere. As such, the examples and teaching style used in this text make absolutely no expectations about your prior programming experience.
12 | 13 |If you've never used a programming language before, leaping into Python might seem a bit scary at first. You don't need to worry. Learning how to program a computer is far from impossible. Anyone can pick up the art of programming with a little time and a bit of patience.
14 | 15 |However, when learning something new, I try to break things. In fact, in many cases, I go out of my way to break stuff. When picking up a new concept like computer programming, you can actually increase your comfort level by figuring out the type of cases that are likely to break. You'll see what data can be used and where, and when you inevitably run into errors later (like everyone does), you won't be surprised.
18 | 19 |The idea that breaking things can actually help you become a better programmer is a central idea in this book, and I hope that you take full advantage. I've broken a lot of code in my day, whether intentionally or not, and I think that it's given me the knowledge to help teach other people how to write good code.
20 | 21 |Learn Python, Break Python starts with a gentle introduction to programming. Slowly, through examples and exercises, we build up to a level of comfort by introducing more complicated program elements, and show where they can be used and how we can break them. By building up knowledge in this way, we hope to impart a level of comfort that will make you comfortable trying new things and taking risks; in short, we want you to be comfortable with programming.
24 | -------------------------------------------------------------------------------- /site/section/c1.html: -------------------------------------------------------------------------------- 1 |Hi there! We've never met, but it's a pleasure to meet you. My name is Alexander, and I'm a programming enthusiast. I really like writing code, and I'm glad that you're interested as well. I'm guessing that you might have some background in programming, or perhaps it's a completely new concept for you. Either way, you must be curious about writing code. It is a pleasure to meet you under these circumstances.
4 | 5 |If you've never used a programming language before, leaping into Python might seem a bit scary at first. You don't need to worry. Learning how to program a computer is far from impossible. Anyone can pick up the art of programming with a little time and a bit of patience. With practice, you'll have the ability to develop programs to play games, verify homework assignments, simulate real world situations, and do almost anything else you can imagine. Sure, it sounds lofty, and your first steps will be humble, but after a few sessions at the keyboard, you'll find out just how much power a programmer has.
6 | 7 |This book deals with Python for good reasons. Python is a powerful language designed to easily develop simple programs. In Python, when you want to write a program to say hello to someone, you write a single line of code. In other languages, this simple task can involve a lot of additional overhead that can be unnecessarily confusing. Python's syntax helps new programmers understand the important concepts without resorting to details that can make a program hard to read.
8 | 9 |Python is frequently used to teach elementary programming skills. Many of the more esoteric concepts in programming have been pushed aside so that the fundamental data structures can be understood with as little head-scratching as possible. It's also a great language for a wide range of tasks, and I'm convinced that it is the perfect way to get you programming quickly and confidently.
10 | 11 |This book is designed to be used by novice programmers, and in particular by people who have no experience with programming whatsoever. We all have to start somewhere. The examples and teaching style used in this text make absolutely no expectations about your prior programming experience. You might be a professional looking to learn programming to help you with your job, you might be a student in school hoping to use programming to help with your homework or to build games, or you might be a curious kid hoping to get your computer doing some really cool stuff. Regardless of your age, you're probably new to programming, and that's great. This book has been written for you.
14 | 15 |Most importantly, this book is for people who are excited about learning how to program! You should be curious about how computers do what they do, and you should be inspired enough to want to become someone who writes software to solve problems. It might sound silly to say this, but programming can be a lot of fun. It's rewarding to execute an idea on the computer that was previously just an idea in your head. I still remember the first time my chess program played its first move against me! You'll have your own exciting moments, and I hope that this book will help make them happen.
16 | 17 |My goal with this book is to introduce programming in a clear and straightforward way, and to answer the questions you're likely to face along the way. Students often ask some very advanced questions, and I have a hard time saying no when the material is so interesting. It's always been unsatisfying for me to be told that I don't have enough experience yet to really understand what's going on when I ask a hard question. With that in mind, this book will introduce some advanced concepts in as clear a way as possible, and expand on them later in detail. I'll always try to avoid saying "just trust me," because you should always have the option to learn something you want to, even if the details are slightly more complicated than you have the background to fully grasp. You'll get there, and you should know these facilities exist, so I'm willing to let you play with something tricky if it helps you understand how a computer needs you to advise it how to act. In fact, we often learn the best lessons by breaking stuff! Fortunately, with programming, we're unlikely to break anything in a serious way, so we can take more chances and learn better lessons.
18 | 19 |What's the deal with being advised to break stuff anyway? That's not the type of thing that you're generally recommended to do. It's not even necessarily something that I go out of my way to apply when working.
22 | 23 |However, when learning something new, I try to break things. In fact, I go out of my way to break stuff. When picking up a new concept like computer programming, you can actually increase your comfort level by figuring out the type of cases that are likely to break. You'll see what data can be used and where, and when you inevitably run into errors later (like everyone does), you won't be surprised.
24 | 25 |There really isn't any risk to you or to your computer by breaking your program code either. You never need to worry about formatting your hard drive by trying to multiply a string and a negative number, and you won't set a fire by forgetting a symbol in your math equations. You should feel comfortable knowing that a big wall of red text indicating an error is just another opportunity to learn.
26 | 27 |The idea that breaking things can actually help you become a better programmer is a central idea in this book, and I hope that you take full advantage. I've broken a lot of code in my day, whether intentionally or not, and I think that it's given me the knowledge to help teach other people how to write good code.
28 | 29 |Programming is a creative process, and you can learn some of the most important things by experimenting. Breaking code and causing errors are great ways to deeply understand how things work. Once you've built up the foundations you need to understand what a program is and why it's structured in a certain way, you'll be well on your way to writing your own code. This book will start with some very basic examples. It's important that you remember that we're starting small on purpose. By the end of the book, we'll be developing some real code that tackles larger problems, giving you a roadmap for developing your own big projects. You're always encouraged to modify the examples in the text, to change names and orderings, and especially to break things to see exactly what the code does.
32 | 33 |Best of luck, and I hope you enjoy the journey!
34 | -------------------------------------------------------------------------------- /site/index.php: -------------------------------------------------------------------------------- 1 | 16 | 17 |This chapter will explain what the programming environment you'll be using is all about, including how to save your programs, and how to use Python to run them. It will also show you how to get going if you're on a Windows machine or on a Mac, and how to get started in the actual development environment, called the interpreter.
4 | 5 |Python isn't guaranteed to be installed on your computer by default, so it might be necessary for you to have access to a computer that you can install software on. The operating system that you're using doesn't matter; Python has downloadable software packages for computers running Windows, Macs, and Linux. The examples in this book will run on any system.
6 | 7 |To make our initial Python experience as easy as possible, we're going to use a development environment called IDLE. It should come by default with the distribution of Python that you download, and this chapter will explain where you can find and install everything needed. But first, what is a development environment, and why would we want to use it?
10 | 11 |Let's start by thinking about a simple calculator. If you want to send a simple addition request to your calculator, you enter the first number, followed by the plus key, then the second number, and finally the equals key. The calculator responds with the answer by displaying it on the screen. That's great, and it's certainly very intuitive for simple equations. When you start to increase the complexity of your commands though, the calculator becomes a little trickier to use. What if you want to get the sum of the square of the first number and the square root of the second number? What about calculating the value of the first number to the power of the second number times the first number squared divided by a third number plus the first number? Obviously these examples are a little bit silly, but there are plenty of real examples that get progressively more difficult to perform with a calculator. How about interest rates over several years, or the average height of a classroom full of students?
12 | 13 |A programming language is a way of organizing commands to write computer programs. With a calculator, you can think of the programming language as consisting of the set of symbols that you can enter on the keypad, and the acceptable orderings in which those symbols can be structured. The programming language of your simple calculator will accept programs like 3 + 4 for two reasons. First, each of the three symbols has meaning. The symbol 3 is a way for the calculator to express the number three, and the symbol 4 expresses the number four. The plus symbol indicates that addition will be used. Second, the addition sign has a number on the left and on the right. In total, 3 + 4 is a meaningful statement that can be evaluated by your calculator, and so in this context, it is a valid program.
14 | 15 |This leads to the development environment. Why is a development environment beneficial for a programmer? It might be helpful to think of the calculator as a development environment for mathematics. While it is possible to perform addition and multiplication in our head, the development environment provided by the calculator allows us to externalize those equations clearly and efficiently. The calculator is a tool for performing math in the same way that a development environment is a tool for allowing programmers to easily write program code.
16 | 17 |There are lots of ways to build programs using Python, and although I recommend IDLE as a tool to get you started, you can work in other development environments if it suits you. If you're new to this, it's probably best to work in IDLE for now. As you begin to write more complicated code, you should feel free to explore other options.
18 | 19 |IDLE is included in most distributions of Python, including the official one that we're going to use. You can get this distribution from the Python homepage at http://python.org in the Downloads section. Be careful though, as there are a couple of things that you'll need to be aware of before downloading your Python distribution.
22 | 23 |At this time, there are two versions of Python that are actively used and maintained. Why are there two versions? There is a lot of industry code running Python 2, and a lot of other code out there that people still depend on. Python 3 is a strong version of the language that fixes some important issues with the design (and that are outside the scope of this book). Python 2 code looks a lot like Python 3 code, so you'll need to make sure you've got the right version. Version 2.7 (or any version starting with a 2) is the older version of the language. This book uses Python 3, so make sure you download one of the version 3 packages. The 2.x language has some subtle differences that will give you some unexpected errors if you download and install it by accident. We want version 3.
24 | 25 |Also, be careful to read the fine print, and make sure you get the correct version for your operating system. If you're on a Windows machine, the first link (Windows Installer, does not include source) is probably enough for you. If you're not sure whether or not your machine is 64-bit, don't worry about it. You can just download the Windows file that is labelled as a generic Windows binary instead of the 64-bit one. The 64-bit version allows you to access more memory when you're writing programs, and for our purposes, we won't need to do that. Even if you are on a machine that supports it, we don't want to get caught up in unnecessary details, especially when most people are using the 32-bit distribution by default anyway.
26 | 27 |Once you download and install the Python distribution, you're ready to go! On a Windows machine, your Python installation can be found under the Start Menu in a folder named "Python 3.x" (where the x corresponds to the version you downloaded). Mine is called "Python 3.3.3", and if that's not the latest and greatest by the time you're reading this sentence, it's probably time for me to upgrade to a newer version. The IDLE development environment is in that Start Menu folder. On a Mac, Python will be placed in your Applications folder, and the IDLE shortcut should be in there too.
28 | 29 |When you double-click on the IDLE icon, you should see something similar to the following:
30 | 31 |
32 | Python 3.3.3 (v3.3.3:c3896275c0f6, Nov 18 2013, 21:18:40) [MSC v.1600 32 bit (Intel)] on win32
33 | Type "copyright", "credits" or "license()" for more information.
34 | >>>
35 |
36 |
37 | If you get into IDLE and see the three greater-than signs right below the copyright/credits line, your installation has been successful. Congratulations, and welcome to IDLE!
38 | 39 |So now that we're here, how do we actually use IDLE? What are those three greater-than signs anyway? Well, the three greater-than signs are the IDLE prompt, which we'll just refer to generically as the prompt. If I say "Type x at the prompt," I'm asking you to type x right after those signs. As an example, try asking Python what 2 plus 4 is. You can just type 2 + 4 in at the prompt, like this.
42 | 43 |>>> 2 + 4
44 | 6
45 | >>>
46 |
47 |
48 | Looks good! Python handles math like your calculator does. You use the symbols on your keyboard to tell Python what equations you'd like to solve, and it goes off and processes that information to get you an answer. The answer to 2 plus 4 is indeed 6, just as expected.
49 | 50 |It's also nice to note that we got another prompt immediately after we got our answer. In the Python environment, the prompt will continue to request commands one after the other until you explicitly exit out of IDLE. You won't need to restart IDLE after you run a program or type in an equation like this. After one program is done, it gets ready to start up the next one.
51 | 52 |As we talked about earlier, the development environment for Python is like a program that sits on top of the Python engine. Python waits, hidden neatly behind those three greater-than signs, eager to get commands from us. If we write a program inside of IDLE, or we use IDLE to send Python statements to the engine, it'll chug away and give us some answers through the development environment window.
53 | 54 |Let's try multiplication next. You might have seen the asterisk (the star) used as a multiplication symbol, as in 3 * 4. Instead of 3 x 4 or 3 times 4, Python expects 3 * 4. Try typing 3 * 4 at the IDLE prompt and see what Python tells you.
55 | 56 |
57 | >>> 3 * 4
58 | 12
59 |
60 |
61 | Perfect, we got the expected result of 3 times 4. Make sure to make a mental note that multiplication uses the asterisk. Also note that I've omitted the prompt that followed the answer, since we're going to see that regardless when single statements like addition or multiplication complete. In the rest of this book, I'll stick to this convention, where the opening prompt will be given when we're typing something into IDLE in this way, but the empty prompts that come up once the statement is finished will be omitted.
62 | 63 |Even at this early stage, we're still completely capable of breaking Python, so let's go ahead and do it. If we know that we can add and multiply numbers, it's a safe assumption that we can do other mathematical operations. What about division? In Python, the division operator is the forward slash sign.
66 | 67 |
68 | >>> 12 / 3
69 | 4.0
70 |
71 |
72 | One good way to gum up a calculator is to try to divide by zero. There is no meaning to the answer, as there is no number that can be multiplied by zero to give a non-zero answer. So what happens if we try to divide by zero in Python?
73 | 74 |
75 | >>> 12 / 0
76 | Traceback (most recent call last):
77 | File "<pyshell#3>", line 1, in <module>
78 | 12 / 0
79 | ZeroDivisionError: int division or modulo by zero
80 |
81 |
82 | Ouch! Welcome to Python's error handling system. If you break something, chances are good that you're going to get something called a traceback, followed by a bunch of information about what broke and how. To be brief, we tried to divide by zero, and Python gave us something called a ZeroDivisionError. These error messages are called exceptions, and are used by Python to get out of a bad situation gracefully instead of crashing your computer. The programming environment was able to detect that we'd tried to do something silly, and halted before any real danger could spring up.
83 | 84 |This book will get into more detail about dealing with exceptions properly in a later chapter. Yeah, even though this book will show you lots of ways to break stuff, we'll have to learn how to fix them eventually too. Until then, we're going to be seeing many more exceptions, so let's go ahead and bring up one more to get better acquainted.
85 | 86 |A common way of writing multiplication expressions on paper is to use parentheses. For example, if we want to multiply the result of 1 + 2 and 3 + 4, we can write something like this:
87 | 88 |
89 | >>> (1 + 2) * (3 + 4)
90 | 21
91 |
92 |
93 | When we do this on paper, it's common to omit the multiplication operator and to just leave the parentheses. For example:
94 | 95 |
96 | >>> (1 + 2) (3 + 4)
97 | Traceback (most recent call last):
98 | File "<pyshell#8>", line 1, in <module>
99 | (1 + 2) (3 + 4)
100 | TypeError: 'int' object is not callable
101 |
102 |
103 | So what's the big deal here? We might expect Python to evaluate the expression (1 + 2), then the expression (3 + 4), and then to multiply the two numbers together in the same way that we saw before. Unfortunately for us, that's not how the interpreter works.
104 | 105 |Python, and programming languages in general, work with a tightly structured grammar. Expressions are a good example of this. You and I might be able to look at the expression above and see that the two values should be multiplied together. Python makes no such assumption about the code. If you leave out operators like the multiplication or division signs, you'll start to see traceback warnings like this.
106 | 107 |This particular TypeError warning comes from Python's evaluation of the first part of the expression, then detecting an open parenthesis.
108 | 109 |
110 | >>> 1 (2 * 3)
111 | Traceback (most recent call last):
112 | File "<pyshell#11>", line 1, in <module>
113 | 1 (2 * 3)
114 | TypeError: 'int' object is not callable
115 | >>> 1 * (2 * 3)
116 | 6
117 |
118 | This is a common error for beginners, so hopefully it will be helpful to see it early. If you want to break Python code, leave out some operators!
119 | 120 |By this point, you should have the correct version of Python installed, along with a bit of experience working inside of the IDLE development environment. Congratulations, you've already started programming in Python! It was mentioned in the introduction that the introductory programming period would be humble, so please don't be discouraged if it seems like all you've done is added and multiplied a few numbers together. We're building a strong foundation to construct larger programs later on. And hey, multiplying numbers isn't easy! Feel free to drop some larger numbers in there too and see how Python handles it.
123 | 124 |In the next chapter, we're going to learn how to save a result in memory using something called a variable, which will allow us to write more complicated and more interesting programs.
125 | 126 |1) Construct some different equations using larger numbers and solve them using IDLE. For example, what is 12345 * 12345? How about 3 * 4 * 5?
129 | 130 |2) You can write negative numbers by adding a dash immediately before the number, with no space. What does Python say when you ask for the result of -1 * 2? What about -1 + -1? Remember to always omit the space between the dash and the number when making negative values.
131 | 132 |3) Whitespace is important in Python, but you have some flexibility. Try adding extra spaces and see where Python complains about it and where it doesn't. For example:
133 | 134 |
135 | >>> 2 + 2
136 | 4
137 | >>> 2 + 2
138 | 4
139 | >>> 2 + 2
140 | SyntaxError: unexpected indent
141 |
142 | 4) Operators like * and + depend on expressions. So far, an expression has been a valid mathematical equation, or a single number. Try making some longer equations using all of the operators we've seen so far. For example, you might start with 2 + 3, and swap out the 2 for another expression to get (1 + 1) + 3. Does this give the same answer at the prompt? How long can you make your expression?
143 | 144 |5) Make a list of the error messages (SyntaxError, TypeError, and so on) that you've seen so far. Do you understand why Python complained about each one? If not, try to go back to reproduce another instance of the error, and see if you can figure out what particular problem forced Python to holler.
145 | -------------------------------------------------------------------------------- /site/section/c13.html: -------------------------------------------------------------------------------- 1 |With the introduction of functions, a new world of additional resources has been opened up. Python has a large number of libraries, referred to as modules, that can be imported and used by your programs. They are similar to the built-in functions, but large sets of libraries have specific purposes. This chapter will discuss a few of the available modules and will explain how to get them into your program and how to take advantage of them.
4 | 5 |You've seen a number of what we've referred to as built-in functions already. These functions are a core part of the Python language. Using the len, max, or print functions is a trivial task; just type in the keyword along with the required parameters, and the correct values are returned. Even mathematical operators, such as the addition and multiplication symbols, are available right out of the box.
8 | 9 |One of the mathematical functions that we've missed is the square root. This is a fairly common operation in math, but certainly not one that is as common as adding or multiplying. As it turns out, Python does offer a way to access the square root function. To get there, we'll need to import a module called math.
10 | 11 |The math module is a collection of mathematical functions that are less common than the core functions, but still very likely to be required in your programs at some point. To access them, we use an import statement and specify the name of the module.
12 | 13 |
14 | import math
15 |
16 |
17 | It's as easy as that. Now, we've got access to the full suite of functions inside the math module. When calling a function inside of a module, you need to specify the module itself where the function exists in addition to the function name. It's not quite like writing a function and just calling getNumber. Modules define a namespace, and methods like sqrt (the square root function that we're about to encounter) exist inside that namespace. The namespace is referenced like this:
18 | 19 |
20 | >>> import math
21 | >>> math.sqrt(4)
22 | 2.0
23 |
24 |
25 | This function call looks almost exactly like the other function calls except for the fact that a module is specified with the function. With the module imported, methods in math can be used just like the other functions. Let's modify the division program from earlier so that the square root function is used instead.
26 | 27 |
28 | import math
29 |
30 | def getNumber(minimum_value=False, input_text="Enter a number: "):
31 | done = False
32 | while not done:
33 | try:
34 | user_number = int(input(input_text))
35 | except ValueError:
36 | print("You didn't enter a number! Shame on you.")
37 | continue
38 | if minimum_value == False or user_number >= minimum_value:
39 | done = True
40 | else:
41 | print("Your number was too low!")
42 | print("The minimum value is {0}.".format(minimum_value))
43 | return user_number
44 |
45 | user_number = getNumber(minimum_value=0, input_text="Enter a number to obtain the square root: ")
46 | print("The square root of {0} is {1}.".format(user_number, math.sqrt(user_number)))
47 |
48 | Enter a number to obtain the square root: 25
49 | The square root of 25 is 5.0.
50 |
51 |
52 | A call to math.sqrt requires a single numeric value as input, and a float number equal to the square root of the source parameter is returned. The math module has a whole set of useful functions, serving as an ideal example of a situation where you'd benefit from offloading a suite of related functions into a single location.
53 | 54 |Included in the math functions are some helpful rounding operations. The round function is available as a built-in function, so we don't need to import math to use it. Two additional functions called ceil (short for ceiling) and floor can be used to round-up or round-down.
55 | 56 |
57 | import math
58 |
59 | x = 2.4
60 | print("x = {0}".format(x))
61 | print("Round: {0}".format(round(x)))
62 | print("Ceiling: {0}".format(math.ceil(x)))
63 | print("Floor: {0}".format(math.floor(x)))
64 |
65 | x = 2.4
66 | Round: 2
67 | Ceiling: 3
68 | Floor: 2
69 |
70 |
71 | Another useful module called random contains several random number generators, along with other related functions including ways to randomise sequences like lists.
72 | 73 |Let's say, for example, that you wanted to build a dice-rolling program.
74 | 75 |
76 | import random
77 |
78 | for i in range(10):
79 | print("Rolling a six sided die: {0}".format(random.randint(1, 6)))
80 |
81 | Rolling a six sided die: 3
82 | Rolling a six sided die: 1
83 | Rolling a six sided die: 4
84 | Rolling a six sided die: 5
85 | Rolling a six sided die: 3
86 | Rolling a six sided die: 2
87 | Rolling a six sided die: 1
88 | Rolling a six sided die: 6
89 | Rolling a six sided die: 4
90 | Rolling a six sided die: 3
91 |
92 |
93 | The random.randint function takes two numbers and returns a random number inside the inclusive range defined by the input. What that means is that in the example above, we're asking for an integer between 1 and 6.
94 | 95 |You can also use the random module to shuffle lists of data in place, similar to sorting or reversing a list. Let's use random to build a list of randomly-generated integers, to sort and shuffle the list, and then to return an element at random.
96 | 97 |
98 | import random
99 |
100 | my_list = []
101 | for i in range(10):
102 | my_list.append(random.randint(1, 100))
103 | print(my_list)
104 |
105 | my_list.sort()
106 | print(my_list)
107 |
108 | random.shuffle(my_list)
109 | print(my_list)
110 |
111 | print(random.choice(my_list))
112 |
113 | [52, 39, 54, 62, 59, 95, 98, 10, 45, 28]
114 | [10, 28, 39, 45, 52, 54, 59, 62, 95, 98]
115 | [54, 10, 39, 98, 95, 59, 52, 62, 45, 28]
116 | 39
117 |
118 |
119 | An an interesting aside, "random" numbers, are actually "pseudo-random". These numbers only appear random. A random number generator has a seed value that acts as a way of determining the starting random number, along with all successive random values after that. If you start with the same seed every time, you actually get the same set of random numbers. Generally, the computer will use its clock time as the starting seed, so unless you have the ability to travel back in time to the same exact moment that your code was executed the first time, you're extremely unlikely to have the same random values showing up. You can play with this quirk by setting the random seed manually and generating lists of random values.
120 | 121 |
122 | import random
123 |
124 | print("Random lists with a random seed:")
125 | for x in range(5):
126 | my_list = []
127 | for i in range(10):
128 | my_list.append(random.randint(1, 100))
129 | print(my_list)
130 |
131 | print("Random lists with a non-random seed:")
132 | for x in range(5):
133 | my_list = []
134 | random.seed(0)
135 | for i in range(10):
136 | my_list.append(random.randint(1, 100))
137 | print(my_list)
138 |
139 | Random lists with a random seed:
140 | [87, 10, 92, 61, 42, 3, 21, 32, 85, 11]
141 | [63, 96, 27, 95, 54, 97, 94, 77, 3, 85]
142 | [93, 13, 7, 58, 69, 3, 30, 48, 40, 30]
143 | [47, 79, 13, 74, 14, 95, 41, 8, 60, 66]
144 | [90, 18, 41, 72, 8, 77, 24, 45, 6, 85]
145 | Random lists with a non-random seed:
146 | [85, 76, 43, 26, 52, 41, 79, 31, 48, 59]
147 | [85, 76, 43, 26, 52, 41, 79, 31, 48, 59]
148 | [85, 76, 43, 26, 52, 41, 79, 31, 48, 59]
149 | [85, 76, 43, 26, 52, 41, 79, 31, 48, 59]
150 | [85, 76, 43, 26, 52, 41, 79, 31, 48, 59]
151 |
152 |
153 | Wacky, eh?
154 | 155 |We'll talk more about additional modules as we move forward. For now, let's look at how you can write your own modules to save time by not copying and pasting the useful functions you develop. Naturally, modules can be defined by a programmer. If you've got a few input function helpers to get numbers or other values, you can set up your own importable module that will make it easier to write the code you want to write.
158 | 159 |To begin, let's create a new file in IDLE. Save it with the name getinput.py, and don't forget the .py extension! This new file will become the module to import. You can think of the import statement as a way of asking Python to include an existing file right into your code at the point where you include the import statement. Any functions that you define in getinput.py will then become accessible to your source code that imports getinput in the future. Let's start with the previous getNumber function. Copy and paste getNumber into the new getinput.py source file, and save it.
160 | 161 |Now go back to your other source code file, and at the very top of the file, write the following lines:
162 | 163 |
164 | import getinput
165 |
166 | getinput.getNumber()
167 |
168 |
169 | You don't need the .py extension in import; Python is able to infer that an import is asking for a file that ends in .py, so you can just omit the extension. Now try to run your file. If all goes well, you should see the following:
170 | 171 |
172 | Enter a number:
173 |
174 |
175 | If you see that, congratulations! You've written a module! You no longer have to copy and paste getNumber in each of your future source files. You can just import the getinput module, a Python source file that you've written yourself and placed in the same directory as your source file, and you've got access to the right functions. Remember, you need the getinput prefix for the getNumber function, and the module has to be in the same directory as your current working file so that Python can find it.
176 | 177 |Let's add some more code to getinput. How about a function that asks the user for a minimum and a maximum value, and returns a random number in that range using the random module. In getinput.py, add the following line to the top of the file.
178 | 179 |
180 | import random
181 |
182 |
183 | And at the bottom of the file, add the following new function.
184 | 185 |
186 | def getRandomRangeNumber():
187 | min_number = getNumber(input_text="Enter the minimum value: ")
188 | max_number = getNumber(minimum_value=min_number, input_text="Enter the maximum value: ")
189 | return random.randint(min_number, max_number)
190 |
191 |
192 | This is a new function that asks the user for a minimum value and a maximum value that must be at least as big as the minimum they just entered. Using this range, it queries random.randint for a random number, and returns it.
193 | 194 |Why doesn't the new getRandomRangeNumber need to prefix the calls to getNumber with the getinput namespace? It's because getRandomRangeNumber is in the same namespace; all the functions in the same namespace know about each other, so if you're calling one from the other, you don't need to specify that we're in the current file.
195 | 196 |Now let's modify the original source that uses getInput so that it calls the new method we just wrote.
197 | 198 |
199 | import getinput
200 | print(getinput.getRandomRangeNumber())
201 |
202 | Enter the minimum value: 5
203 | Enter the maximum value: 25
204 | 18
205 |
206 |
207 | If you want to add in additional methods to your module, just place them in getinput.py and they'll be accessible to other Python source files that import the module. Awfully convenient, isn't it?
208 | 209 |In some rare instances, you might want to only import a small section of the module. It might be the case that you feel you'll only need the sqrt function from math, or that you know that a module is itself broken down into further modules -- modules can actually be nested inside one-another, and we'll see an example of this.
212 | 213 |One module that you might get a lot of use from is datetime. The datetime collection of functions and objects gives you a way to collect and manipulate dates and times. It gives you a set of methods for formatting date strings for printing to the screen. It also allows you to perform arithmetic on dates, as you might do when asking for the date two days from now. The now function gives you the current date and time.
214 | 215 |
216 | import datetime
217 | print(datetime.datetime.now())
218 |
219 | 2010-11-24 16:17:58.521000
220 |
221 |
222 | It looks a little unusual when datetime is entered twice like that. This is an artifact of the datetime module and how it's been structured in the original source. It turns out that there's a datetime object inside the datetime module that is responsible for getting values like the current date. The reason for this is that the datetime module does something analogous to defining datetime as a type. It sets up an object called datetime, and that new datetime object is assigned a value corresponding to the current time.
223 | 224 |What? This might be a little confusing, and that's completely fair. The next chapter will talk about classes, and will open up some more of these details. For the moment, consider that importing the datetime module defines the datetime namespace (the first datetime), and inside that namespace is a datetime object (the second datetime) upon which the now function is called. Confused yet?
225 | 226 |For this very reason, we can use a slightly different form of the import statement. We can ask Python to import the datetime object (not the module) directly into the current namespace, instead of into the datetime namespace.
227 | 228 |
229 | from datetime import datetime
230 | print(datetime.now())
231 |
232 | 2010-11-24 16:17:58.521000
233 |
234 |
235 | As a simplification of this, we can also write the following code:
236 | 237 |
238 | from math import sqrt
239 | sqrt(4)
240 |
241 | 2.0
242 |
243 |
244 | The from statement used in conjunction with import asks Python to import a subset of the module instead of the whole thing. In the case of the math module, we ask Python to just bring in the sqrt function, but not the whole module.
245 | 246 |Modules offer a way of organizing large sets of code in the same way that functions allow you to place related lines of code in a single location. They save you the hassle of copying and pasting the functions you use most frequently by tucking them away behind an import statement, ready to be used at your demand. If you don't need to use them, they're still safely organized in your source code directory.
249 | 250 |These abstractions move programming from a hacky collection of random lines of code towards a well-structured piece of engineering. In fact, when we refer to software engineering as a practice, it is with the intent of approaching the rigour that professional engineers in the physical sciences apply to their work. When building a bridge, the designers go to great lengths to ensure that everything makes sense, to prevent the bridge from collapsing. It might seem strange to think about software in the same way at first, but when you consider that software is now found in cars, airplanes, and hospital equipment, the demand on software developers to write well-structured and maintainable code is greater than ever. Functions and modules are a step in this direction, and a step away from the chaotic development practices that many developers fall in to.
251 | 252 |With practice, you'll figure out the best ways to structure your code, giving you an ideal amount of reuse and a minimal amount of rewriting. It's always really nice to find yourself in need of a function, and then realizing that you're already written it and can import it with a single line of code.
253 | 254 |1) Go back and look at some of the code that you're written previously when working through this book. Find some examples that you might like to use in other programs that you write, and extract them out to a module. Save the file in your working directory, and write some test programs to import the module and use the new functions.
257 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,Well, we've spent the majority of the book so far learning how to program, and we've broken a bunch of things along the way. Since we've gotten into so much trouble by trying to expose the error systems in Python, maybe it's time to learn how to handle the errors that we keep bringing up.
4 | 5 |In this chapter, we'll learn about error handling--the proper way to catch exceptions when they arise, and how to write code that can recover from what would otherwise have been a fatal error.
6 | 7 |By this point, you've probably run into a few exceptions along the way. At least, I hope you have! We're setting out to break as many things as we can in the name of learning, after all!
10 | 11 |Exceptions can happen when you try to convert a string into a number when the string is actually a person's name, or when you misspell a function or variable name forcing Python to complain that it can't find the thing that you're trying to call. Exceptions are Python's way of identifying where and how a part of your program broke. Once you're able to identify what they mean, you can use these to help fix your code.
12 | 13 |It's probably safe to assume that you've hit a red warning message at some point in your programming. It might have been clear what happened, but it also might have been a total mystery. Some of the error messages can be confusing. Only with experience are you able to make the most sense of them. Other exception messages sound perfectly reasonable, and you might even find yourself understanding how to deal with them in a responsible way.
16 | 17 |Let's look at an example that you might have run into already. We'd like to get a number as input from a user so that we can do some math with it. Maybe we're squaring it, maybe we're adding two. Regardless, we'd like to get a number from the user, and to use the number value, the string value must be converted. What happens when the user enters a word, or for that matter, any non-numeric value, and the conversion is omitted?
18 | 19 |
20 | >>> user_number = int(input("Enter a number: "))
21 | Enter a number: Alexander
22 | Traceback (most recent call last):
23 | File "<pyshell#2>", line 1, in <module>
24 | user_number = int(input("Enter a number: "))
25 | ValueError: invalid literal for int() with base 10: 'Alexander'
26 |
27 |
28 | Python complains in bright red text about a ValueError exception, and states that the string "Alexander" is an invalid literal for int() with base 10. So what on Earth does that mean? It's pretty clear that int was given a value that can't be converted into a number. Why did Python actually throw a bright red error and terminate the program in this way? Is this really the graceful way to handle the problem?
29 | 30 |Let's try another example to get Python to halt program execution with another exception. Consider the case where we get an acceptable number, but a number that breaks the mathematical operation we'd like to use.
31 | 32 |
33 | >>> user_number = int(input("Enter a number: "))
34 | Enter a number: 0
35 | >>> print("10 divided by {0} is {1}.".format(user_number, 10/user_number))
36 | Traceback (most recent call last):
37 | File "<pyshell#4>", line 1, in <module>
38 | print("10 divided by {0} is {1}.".format(user_number, 10/user_number))
39 | ZeroDivisionError: int division or modulo by zero
40 |
41 |
42 | This sample code broke because we tried to divide 10 by 0, which is undefined. Python threw the appropriately-named ZeroDivisionError to indicate that this was the specific problem.
43 | 44 |An exception is Python's way to break the code in a reasonable and safe way that can actually be identified by your program. For example, if it is known that a division operation could potentially attempt to divide by zero causing a ZeroDivisionError, we could tell the code to watch for this error message, and to handle it gracefully if it happens. In the ValueError example, a loop could be repeated as long as ValueError exceptions came back from int, since a ValueError exception means that the user is trying to enter in values that aren't accepted by the int function.
45 | 46 |Fortunately, there is functionality to attempt to run a program with the knowledge that some part of the code might actually throw an exception. It's like saying that you know you're asking the user to enter in a value, but you also know that they're capable of giving you bad data. You'd like to try to run this block of code, and if an exception comes back, you'd like to handle it in an appropriate way.
49 | 50 |In the ValueError example, let's make a very simple piece of code that attempts to convert the input to an integer, and to catch a ValueError if the user gives inappropriate data.
51 | 52 |
53 | try:
54 | user_number = int(input("Enter a number: "))
55 | print("Your number is {0}.".format(user_number))
56 | except ValueError as e:
57 | print("You didn't enter a number! Shame on you.")
58 | print(e)
59 | print("All done!")
60 |
61 | Enter a number: 10
62 | Your number is 10.
63 | All done!
64 |
65 | Enter a number: Alexander
66 | You didn't enter a number! Shame on you.
67 | invalid literal for int() with base 10: 'Alexander'
68 | All done!
69 |
70 |
71 | This is certainly much better than a program crash! If the program gets an acceptable value, everything goes as planned and the except block never gets executed. However, Python understood that there was a block of code that might throw a ValueError exception, and if it happened, it should stop immediately and execute the code that prints out a stern rebuke. Notice that it really does exit immediately. A try block is your way of asking Python to cautiously execute the code, and to get out of there as soon as possible once an Exception occurs. That's why you don't see the "Your number is" string when the bad value is given. Python gets out as soon as the int statement occurs.
72 | 73 |If you want to access detailed information about the specifics of the crash, you can add "as e", or "as (variable_name)" to the except statement. That gives you the ability to have a statement like print(e) that gives more information about the details of the exception being raised. In future examples, we generally won't need to deal with those details, and the "as (variable_name)" component will be safely omitted.
74 | 75 |Once the try block and corresponding except block are finished, the program continues on as it normally would. There really is no crash here when an exception is raised and caught. Python catches the exception, does something with it (if you'd like to do something at all), and then moves forward as if everything was fine. Presumably you would use the except block to make sure that your program state was in a good place moving forward.
76 | 77 |What about the division case? If for some reason the division needs to occur, we don't want to move forward without a valid number. Let's write a loop.
78 | 79 |A try block can occur inside of a loop, and we can use try blocks to carefully identify only the pieces of code that are potential candidates for exceptions to occur. Let's rewrite the ZeroDivisionError code to loop until a valid number occurs, and to do the division once everything is finished and we are sure that a good number has been placed in user_number. First, here is the naive case that tries once to get a valid number.
80 | 81 |
82 | try:
83 | user_number = int(input("Enter a number other than zero: "))
84 | division = 10 / user_number
85 | print("10 divided by {0} is {1}.".format(user_number, 10 / user_number))
86 | except ZeroDivisionError:
87 | print("A number other than zero, please!")
88 |
89 |
90 | From this, let's move the try block inside of a loop.
91 | 92 |
93 | done = False
94 | while not done:
95 | user_number = int(input("Enter a number other than zero: "))
96 | try:
97 | division = 10 / user_number
98 | done = True
99 | except ZeroDivisionError:
100 | print("A number other than zero, please!")
101 | print("10 divided by {0} is {1}.".format(user_number, 10 / user_number))
102 |
103 | Enter a number other than zero: 0
104 | A number other than zero, please!
105 | Enter a number other than zero: 0
106 | A number other than zero, please!
107 | Enter a number other than zero: 25
108 | 10 divided by 25 is 0.4.
109 |
110 |
111 | With the try-block nicely nested inside the while loop, we get away from the messy example of wrapping the entire block in a try section. It really is only the division operation that can cause this problem, so that single line is wrapped in a try block along with the only modification to done that can terminate the while loop. If the division raised a ZeroDivisionError, the statement that sets done to True never gets hit because Python swiftly shifts the program execution into the except block.
112 | 113 |A keen observer will have noticed that we have the exact same ValueError problem in this new code. There's nothing to stop a malicious user from entering a word in the input block, and the try statement in the code above won't catch bogus strings that can't be converted into integers.
114 | 115 |Try blocks can have multiple except conditions, just like if-statements can have multiple elif blocks followed by an else block. If the input statement is moved inside the try block, and another except statement is introduced to catch ValueError exceptions, the code might look like this:
116 | 117 |
118 | done = False
119 | while not done:
120 | try:
121 | user_number = int(input("Enter a number other than zero: "))
122 | division = 10 / user_number
123 | done = True
124 | except ValueError:
125 | print("You didn't enter a number! Shame on you.")
126 | except ZeroDivisionError:
127 | print("A number other than zero, please!")
128 | print("10 divided by {0} is {1}.".format(user_number, 10 / user_number))
129 |
130 | Enter a number other than zero: Alexander
131 | You didn't enter a number! Shame on you.
132 | Enter a number other than zero: 0
133 | A number other than zero, please!
134 | Enter a number other than zero: 25
135 | 10 divided by 25 is 0.4.
136 |
137 |
138 | This code nicely merges both of the examples seen so far. The code won't crash on a non-numeric string, and it also won't die when a zero value is given. It sits inside of a loop that repeats until a valid condition is obtained, and finally moves on to the goal state where we get to print out the result of the division.
139 | 140 |You are not a slave to exceptions! You don't need to sit idly by waiting to catch them at their fancy. You have the ability to raise exceptions yourself when your code breaks in a unique way.
143 | 144 |To start, we can write a simple loop that duplicates the modulo (mod) operator--a way to determine the remainder of devision of one number by another. For example, if we evaluate the expression 6 mod 4, the result is 2, because 4 goes into 6 one time and leaves a remainder of 2. In Python, we can use the % operator to find the remainder.
145 | 146 |
147 | >>> 6 % 4
148 | 2
149 |
150 |
151 | Now, in the interest of learning something new, and in potentially breaking something in a creative way, let's build a loop that will duplicate this functionality. First, the naive solution looks like this:
152 | 153 |
154 | x = int(input("Enter the first number: "))
155 | y = int(input("Enter the second number: "))
156 |
157 | print("{0} mod {1} is {2}".format(x, y, x % y))
158 |
159 | Enter the first number: 6
160 | Enter the second number: 4
161 | 6 mod 4 is 2
162 |
163 |
164 | We can replace the explicit x % y operation in the print statement with a reference to a variable we create to store the result. Let's try this:
165 | 166 |
167 | x = int(input("Enter the first number: "))
168 | y = int(input("Enter the second number: "))
169 |
170 | m = x
171 | while True:
172 | m = m - y
173 | if m < y:
174 | break
175 |
176 | print("{0} mod {1} is {2}".format(x, y, m))
177 |
178 | Enter the first number: 6
179 | Enter the second number: 4
180 | 6 mod 4 is 2
181 |
182 |
183 | In this example, we replace the modulo operator with a loop. Before the loop begins, we create a new variable called m. In m, we store the value of x, and iteratively subtract y from m until we're left with a value that is less than our divisor. In the case of 6 mod 4, subtracting 4 from 6 once gives us 2, which can't bear another subtraction of the divisor before heading into the negative values. We halt the loop when this condition is met, and in m, the correct value is stored.
184 | 185 |So what's wrong with this code? Well, a number of things. We wouldn't be breaking stuff otherwise.
186 | 187 |First, consider what it means to divide by zero. How many times does zero go into another number? The result of dividing a number of zero is undefined--there's no result that satisfies the expression. We can see this clearly in Python through an exception.
188 | 189 |
190 | >>> 6 / 0
191 | Traceback (most recent call last):
192 | File ">stdin<", line 1, in <module>
193 | ZeroDivisionError: integer division or modulo by zero
194 |
195 |
196 | The program halts, as expected, with the appropriately named ZeroDivisionError exception. Do you see that bit at the end of the expression detail though where it suggests that this is a result of either an integer division by zero or a modulo by zero? What happens if we use the modulo operator with zero?
197 | 198 |
199 | >>> 6 % 0
200 | Traceback (most recent call last):
201 | File ">stdin<", line 1, in <module>
202 | ZeroDivisionError: integer division or modulo by zero
203 |
204 |
205 | Ouch! Same thing. There can't be a remainder after division because we can't even divide by zero in the first place. So what does that mean for our new program?
206 | 207 |
208 | Enter the first number: 6
209 | Enter the second number: 0
210 | ^CTraceback (most recent call last):
211 | File "sample.py", line 5, in <module>
212 | while True:
213 | KeyboardInterrupt
214 |
215 |
216 | The program doesn't end! It repeats in an infinite loop since the terminating condition of m < y can never be true. Subtract zero from m as many times as you want, but m can never be less than y. We're not defeated though. This is just another way to break the code and hint at the solution.
217 | 218 |In the Python implementation of modulo, the correct response is to give the ZeroDivisionError exception when zero is provided as the divisor. We can do the same thing in our code.
219 | 220 |Throwing an exception is done using the raise keyword. By raising an exception, you halt the code at the current point and exit out to a point at which the exception can be caught, or the program can be terminated.
221 | 222 |
223 | >>> raise Exception("Oh no!")
224 | Traceback (most recent call last):
225 | File "<stdin>", line 1, in <module>
226 | Exception: Oh no!
227 |
228 |
229 | An exception is a type of class, which we'll talk about in more detail later. For our purposes, though, we can use exceptions that we know to exist already in our code, especially if we're writing similar blocks of code to fragments that exist in Python. Let's try adding a raised exception to our sample modulo.
230 | 231 |
232 | x = int(input("Enter the first number: "))
233 | y = int(input("Enter the second number: "))
234 |
235 | if y == 0:
236 | raise ZeroDivisionError("modulo by zero")
237 |
238 | m = x
239 | while True:
240 | m = m - y
241 | if m < y:
242 | break
243 |
244 | print("{0} mod {1} is {2}".format(x, y, m))
245 |
246 | Enter the first number: 6
247 | Enter the second number: 0
248 | Traceback (most recent call last):
249 | File "sample.py", line 5, in <module>
250 | raise ZeroDivisionError("modulo by zero")
251 | ZeroDivisionError: modulo by zero
252 |
253 |
254 | Beautiful. We even get our customized message that omits the integer error possibility. You can write whatever you'd like in there.
255 | 256 |And hey, by the way, if you'd like to break some stuff, try adding in negative numbers. This code isn't perfect yet!
257 | 258 |Code can break in lots of ways. In fact, in many cases, code breaks by design. To make sure that our code runs as expected, even in the situation where we're given data that is clearly malformed or inappropriate for our purposes, throwing exceptions is the Pythonic way to handle those errors and to continue or die gracefully.
261 | 262 |In the next section, we will introduce the concept of a function, a way to compartmentalize blocks of code that can be reused without resorting to simply copying and pasting.
263 | -------------------------------------------------------------------------------- /site/section/c10.html: -------------------------------------------------------------------------------- 1 |Believe it or not, you aren't required to rely on input for all your input from a user. If you've got documents, configuration files, or other text documents sitting on your hard drive, these can all be used as input as easily as reading data from the keyboard. In this chapter, we'll build some sample applications that both accept text files as input and write text files as output.
4 | 5 |The input statement is fairly abstract because there's really only one way to query the keyboard for a string. It isn't necessary to tell input to use the active keyboard, to wait until the new line character comes through before it's over, or any other extraneous information. Before we can read input from a file, it is necessary to identify a specific reference to the file itself. With a file, we have two key pieces of information, the location of the file, and whether we'd like to open the file for reading or for writing. To get this file reference, we use the open command. In this example, we use a file in the same directory as the program source code called it hello.txt, containing a single line of text.
8 | 9 |
10 | input_file = open("hello.txt", "r")
11 |
12 |
13 | This open statement uses the file name as the first parameter. Since the file is in the same directory as my source code, we don't need to include the full system path. The second parameter is the single letter "r", which is short for "read". This tells Python that we want to open the file for reading access, meaning that we aren't going to make any changes to hello.txt. We're just going to see what it contains.
14 | 15 |There are a number of different ways to get data contained in the file, but we focus on the two most common ones here. You can either read the entire file into memory at once as a list by using readlines, or you can read a file one line at a time by using the in keyword. For smaller examples, you really won't notice any difference. For larger files, you don't want to load the entire thing into memory at once, so in general, we're going to stick with single lines at a time.
16 | 17 |First, let's take a look at readlines.
18 | 19 |
20 | input_file = open("hello.txt", "r")
21 | lines = input_file.readlines()
22 | input_file.close()
23 | print("The entire hello.txt file:")
24 | print(lines)
25 | print("The hello.txt file, line-by-line:")
26 | for x in lines:
27 | print(x)
28 | print("All done!")
29 |
30 | The entire hello.txt file:
31 | ['Hello world!\n']
32 | The hello.txt file, line-by-line:
33 | Hello world!
34 |
35 | All done!
36 |
37 |
38 | The readlines method is called on the opened file object to read the entire file into memory. This means that when readlines finishes, the returned variable is a list with a length equal to the number of lines in the text file itself. The hello.txt file created earlier is a single line terminated by a new-line character. You can see the results in lines when it is printed to the screen. The list has a length of one and consists of a single string that terminates with the newline character "\n".
39 | 40 |You can see how we can use the list in a loop to access each of the lines in turn. The lines of the file exist in memory now, so individual lines can be accessed by index. Notice that we also called the close method for the input_file file object. When the file is no longer needed, you'll want to make sure that access to the file is stopped. Python will often close files automatically if they're still open when the program terminates, but as your program continues running and you keep opening files again and again, you can run into access problems.
41 | 42 |The alternative way to read the lines from a file is one-by-one. A loop can be used to do this using the file object as an iterator. The format for this is as follows:
43 | 44 |
45 | input_file = open("hello.txt", "r")
46 | print("The hello.txt file, line-by-line using a for-loop:")
47 | for x in input_file:
48 | print(x)
49 | input_file.close()
50 | print("All done!")
51 |
52 | The hello.txt file, line-by-line using a for-loop:
53 | Hello world!
54 |
55 | All done!
56 |
57 |
58 | Each of the lines in hello.txt is accessed by using the in keyword. It requires much less memory when used with larger files, and its syntax is slightly more straightforward. We'll use both in and readlines going forward. You are of course free to use the one that feels most comfortable.
59 | 60 |So far, we've only looked at an input file with a single line of text. How do larger source files appear? As a sample, let's use the Project Gutenberg text version of The Time Machine, by H. G. Wells. This file was downloaded from http://www.gutenberg.org/cache/epub/35/pg35.txt and saved in the same folder as the source code that will attempt to read it.
61 | 62 |
63 | input_file = open("pg35.txt", "r")
64 | lines = input_file.readlines()
65 | print("The input file has {0} lines of text.".format(len(lines)))
66 | print(lines[0])
67 | for x in range(37, 49):
68 | print("{0}: {1}".format(x, lines[x]), end="")
69 | print("All done!")
70 |
71 | The input file has 3604 lines of text.
72 | Project Gutenberg's The Time Machine, by H. G. (Herbert George) Wells
73 |
74 | 37: The Time Traveller (for so it will be convenient to speak of him)
75 | 38: was expounding a recondite matter to us. His grey eyes shone and
76 | 39: twinkled, and his usually pale face was flushed and animated. The
77 | 40: fire burned brightly, and the soft radiance of the incandescent
78 | 41: lights in the lilies of silver caught the bubbles that flashed and
79 | 42: passed in our glasses. Our chairs, being his patents, embraced and
80 | 43: caressed us rather than submitted to be sat upon, and there was that
81 | 44: luxurious after-dinner atmosphere when thought roams gracefully
82 | 45: free of the trammels of precision. And he put it to us in this
83 | 46: way--marking the points with a lean forefinger--as we sat and lazily
84 | 47: admired his earnestness over this new paradox (as we thought it)
85 | 48: and his fecundity.
86 | All done!
87 |
88 |
89 | You might have noticed the change to the print statement in the for-loop above. Since each of the lines is read in by readlines, the real full line of text is accepted. Each of these lines of text actually ends in a newline character, so each of the elements in the list itself has a newline. You can verify this in the interpreter.
90 | 91 |
92 | >>> lines[0]
93 | "Project Gutenberg's The Time Machine, by H. G. (Herbert George) Wells\n"
94 |
95 |
96 | The "\n" character at the end of the string is the newline.
97 | 98 |
99 | >>> lines[37:49]
100 | ['The Time Traveller (for so it will be convenient to speak of him)\n', 'was expounding a recondite matter to us. His grey eyes shone and\n', 'twinkled, and his usually pale face was flushed and animated. The\n', 'fire burned brightly, and the soft radiance of the incandescent\n', 'lights in the lilies of silver caught the bubbles that flashed and\n', 'passed in our glasses. Our chairs, being his patents, embraced and\n', 'caressed us rather than submitted to be sat upon, and there was that\n', 'luxurious after-dinner atmosphere when thought roams gracefully\n', 'free of the trammels of precision. And he put it to us in this\n', 'way--marking the points with a lean forefinger--as we sat and lazily\n', 'admired his earnestness over this new paradox (as we thought it)\n', 'and his fecundity.\n']
101 |
102 |
103 | If you'd like to just acquire the text in each line without the unnecessary whitespace on either end, we can go back to the old string method strip so that the print statement doesn't need to be supplemented with the end parameter. This is usually what I do in my own code, but of course your mileage may vary.
104 | 105 |
106 | input_file = open("pg35.txt", "r")
107 | lines = input_file.readlines()
108 | print("The input file has {0} lines of text.".format(len(lines)))
109 | print(lines[0])
110 | for x in range(37, 40):
111 | print("{0}: {1}".format(x, lines[x].strip()))
112 | print("All done!")
113 |
114 | The input file has 3604 lines of text.
115 | Project Gutenberg's The Time Machine, by H. G. (Herbert George) Wells
116 |
117 | 37: The Time Traveller (for so it will be convenient to speak of him)
118 | 38: was expounding a recondite matter to us. His grey eyes shone and
119 | 39: twinkled, and his usually pale face was flushed and animated. The
120 | All done!
121 |
122 |
123 | When opening a text file, we must decide whether to open the file for reading or for writing. It doesn't realy make sense to do both at the same time, so a distinction between the two is made. For example, when opening The Time Machine, we never intended to rewrite the story. Rather, we were interested in opening the story and reading the data for some purpose.
126 | 127 |Let's consider writing to files first. With writing, the open function is used a similar way as reading, but the second parameter is either "w" for write or "a" for append. If you open a file for appending, any new information written to the file is pasted onto the end.
128 | 129 |When you open a file for writing, a new empty file is created in the specified location. If the file already exists and you use "w", it will be deleted and overwritten by the new file. That's important! Be careful when specifying your target, because it is fantastically easy to overwrite your input file by accidentally using "w" instead of "r" when opening. I speak from experience on this one.
130 | 131 |
132 | output_file = open("output.txt", "w")
133 |
134 |
135 | To start getting data into the file, we can use write. The write function works a lot like print, except that it sends data to a file instead of to the screen. When a string is written to a file, the newline character won't be added unless it is explicitly specified. Let's build a sample program to see how we can start writing user input to a file.
136 | 137 |
138 | output_file = open("output.txt", "w")
139 | print("Enter a few strings to write to the file, and type quit when finished.")
140 | done = False
141 | while not done:
142 | st = input("> ")
143 | if st == "quit":
144 | done = True
145 | else:
146 | output_file.write("{0}\n".format(st))
147 | output_file.close()
148 | print("All done!")
149 |
150 | Enter a few strings to write to the file, and type quit when finished.
151 | > This is a test.
152 | > Writing to a file is fun!
153 | > Wowwwwwww.
154 | > quit
155 | All done!
156 |
157 | output.txt:
158 | This is a test.
159 | Writing to a file is fun!
160 | Wowwwwwww.
161 |
162 |
163 | Now if we run the code a second time and enter in some more data, the original output.txt will be deleted and replaced by the new set of user input. Let's change the "w" in the open function to "a" and see how it works instead.
164 | 165 |
166 | output_file = open("output.txt", "a")
167 |
168 | Enter a few strings to write to the file, and type quit when finished.
169 | > Appending data is also fun.
170 | > quit
171 | All done!
172 |
173 | output.txt:
174 | This is a test.
175 | Writing to a file is fun!
176 | Wowwwwwww.
177 | Appending data is also fun.
178 |
179 |
180 | As long as the data is a string, it can be safely written to the file. Unlike print, write won't automatically attempt to convert your data to a string, so you'll have to do it manually. For example, if we try to write a number to the file, we'll hit a TypeError exception.
181 | 182 |
183 | output_file = open("output.txt", "w")
184 | output_file.write(5)
185 | output_file.close()
186 | print("All done!")
187 |
188 | Traceback (most recent call last):
189 | File "C:\Python33\sandbox.py", line 2, in <module>
190 | output_file.write(5)
191 | TypeError: must be str, not int
192 |
193 |
194 | The way around this is to wrap the number in str to explicitly convert the number 5 into the string "5".
195 | 196 |
197 | output_file.write(str(5))
198 |
199 |
200 | The same thing goes for other data types. Just make sure that the actual conversion is done manually, and write will be able to send the data to the file.
201 | 202 |Now let's take an input file and do some interesting processing on it before writing some new data to an output file. We'll have two file objects, one for input and one for output. For this program, we'll use The Time Machine again, and count the number of words. To do that, we'll strip out any character that isn't a letter and assume that any continuous set of letters makes up a word. For example, let's take an arbitrary string from input and split it up into each of the words one by one.
205 | 206 |
207 | input_string = input("Enter a string: ")
208 | new_string = ""
209 | for x in input_string:
210 | if x.isalpha() or x == " ":
211 | new_string = "{0}{1}".format(new_string, x.lower())
212 | while new_string.find(" ") >= 0:
213 | new_string = new_string.replace(" ", " ")
214 | new_string = new_string.strip()
215 | words = new_string.split(" ")
216 | words.sort()
217 | print("The words in your string are:")
218 | print(words)
219 |
220 | Enter a string: This is a test.
221 | The words in your string are:
222 | ['a', 'is', 'test', 'this']
223 |
224 |
225 | The isalpha function returns True if all of the characters in the non-empty string are alphabetic. In the program above, we look at each letter in input_string one at a time, test whether they are either in the alphabet or are a space, and if they are what we want, concatenate them to new_string. When we're done, new_string should only consist of letters and spaces. Any pattern of two or more spaces is eliminated by replacing two spaces with one space. Finally, split is called to get a list of the words in the string. If we didn't replace all pairs of spaces, split would give us some empty words as results. For example, if you remove the replace call, you can see output like this:
226 | 227 |
228 | Enter a string: This is a test.
229 | The words in your string are:
230 | ['', '', '', '', '', '', '', '', '', '', 'a', 'is', 'test', 'this']
231 |
232 |
233 | Since there can be extra spaces at the start or end of a string that can still throw off the results, we also make a call to strip to clean up the ends. Finally, we sort the word list, and print it to the screen.
234 | 235 |Let's use the same approach with the input file. Instead of printing the entire list to the screen, let's print a subset of the words, along with the length of the word list. The previous code will need a slight modification because the new code will be using multiple lines.
236 | 237 |
238 | input_file = open("pg35.txt", "r")
239 | words = []
240 | for line in input_file:
241 | new_string = ""
242 | for x in line:
243 | if x.isalpha() or x == " ":
244 | new_string = "{0}{1}".format(new_string, x.lower())
245 | else:
246 | new_string = "{0} ".format(new_string)
247 | while new_string.find(" ") >= 0:
248 | new_string = new_string.replace(" ", " ")
249 | new_string = new_string.strip()
250 | if len(new_string) > 0:
251 | for word in new_string.split(" "):
252 | words.append(word)
253 | words.sort()
254 | print("There are {0} words in the file.".format(len(words)))
255 | print("Some of the words in your file are:")
256 | print(words[:10])
257 | print(words[10000:10010])
258 |
259 | There are 35261 words in the file.
260 | Some of the words in your file are:
261 | ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']
262 | ['front', 'front', 'frugivorous', 'fruit', 'fruit', 'fruit', 'fruit', 'fruit', 'fruit', 'fruits']
263 |
264 |
265 | This looks great, and we've got a full list of all the words in the file. However, it would be nice to have each word show up only once. In particular, it would be handy to have a count of the actual number of times each word occurs. Let's change the list to a dictionary and track each word a little more closely.
266 | 267 |
268 | input_file = open("pg35.txt", "r")
269 | words = {}
270 | for line in input_file:
271 | new_string = ""
272 | for x in line:
273 | if x.isalpha() or x == " ":
274 | new_string = "{0}{1}".format(new_string, x.lower())
275 | while new_string.find(" ") >= 0:
276 | new_string = new_string.replace(" ", " ")
277 | new_string = new_string.strip()
278 | if len(new_string) > 0:
279 | for word in new_string.split(" "):
280 | if word in words:
281 | words[word] += 1
282 | else:
283 | words[word] = 1
284 | words_keys = sorted(words)
285 | print("There are {0} words in the file.".format(len(words)))
286 | print("Some of the words in your file are:")
287 | for x in range(10):
288 | print(words_keys[x], words[words_keys[x]])
289 |
290 | There are 5173 words in the file.
291 | Some of the words in your file are:
292 | a 861
293 | abandon 1
294 | abandoned 1
295 | abide 1
296 | able 3
297 | abnormally 1
298 | abominable 2
299 | abominations 1
300 | about 78
301 | above 23
302 |
303 |
304 | Much better! We can see how frequent the words are, and with the sorted keys from the dictionary, it's possible to view a sorted list of the elements of the dictionary.
305 | 306 |Let's go back to writing files so that this information can be saved in an output file. Change the last part of the program to this:
307 | 308 |
309 | words_keys = sorted(words)
310 | output_file = open("output.txt", "w")
311 | output_file.write("There are {0} words in the file.\n".format(len(words)))
312 | output_file.write("Some of the words in your file are:\n")
313 | for key in words_keys:
314 | output_file.write("{0}: {1}\n".format(key, words[key]))
315 | output_file.close()
316 |
317 |
318 | If you run this program and take a look at the new contents of the output.txt file we just wrote, you'll see the following data:
319 | 320 |
321 | There are 5173 words in the file.
322 | Some of the words in your file are:
323 | a: 861
324 | abandon: 1
325 | abandoned: 1
326 | abide: 1
327 | able: 3
328 | abnormally: 1
329 | abominable: 2
330 | abominations: 1
331 | about: 78
332 | above: 23
333 | [..]
334 |
335 |
336 | In a single program, we've managed to read in an entire story line by line, do some word analysis on the data, and send the results to an output file based on the frequency of the words. The amount of data we're looking at is too great to print to the screen at once, so saving it as a file works as a great way to keep track of things. When you have too much data to work with at once, saving as a file can give you a manageable way of handling the information.
337 | 338 |Reading and writing to text files is fairly straightforward using Python. There's an important caveat there though: reading and writing to files that are made up of text data is fairly straightforward. There is another type of data stored in files that is usually referred to as binary data. Binary data doesn't look like sentences or natural language. It's not structured for people to read directly. Instead, it's used by computers to store the data it needs in an efficient way.
341 | 342 |If you try to open a binary file, like an archived zip file, you'll get some strange results on the screen. Consider this simple program:
343 | 344 |
345 | input_file = open("test.zip", "r")
346 | for line in input_file:
347 | print(line)
348 | input_file.close()
349 |
350 |
351 | This code works perfectly fine as long as the input file is made up a collection of individual lines. Each line will be printed to the screen, one-by-one, and the file will be closed. However, as you might have noticed in the code block, we're opening a zip file here. What do we get in this case? Well, in my terminal, I get the following:
352 | 353 |
354 | .]1Dt.pyUX
355 | 7]?R7]?R?+J?,NUp?HN-(????P??P??WT???P??H.]1D??H?
356 | ??t.pyU7]?R7]?RPK>_
357 |
358 |
359 | Not particularly helpful. This file actually consists of a single python file that I created as an example called t.py. You can see hints that the file name is stored in the binary data. However, the contents of the file are compressed and unreadable, so what you get on the screen is a bunch of spaghetti.
360 | 361 |Note that Python didn't crash when we tried to open a binary file in this way. All that we said was to open the file and to treat it as a text file with line breaks. There were no exceptions and no bright red warnings. The output was the only clue that we'd done something unexpected.
362 | 363 |Reading and writing information using text files is a common operation in Python that is implemented in an elegant way. Reading a file looks just like accessing elements in a list, and writing strings to a file is extremely similar to printing to the screen.
366 | -------------------------------------------------------------------------------- /site/section/c4.html: -------------------------------------------------------------------------------- 1 |Most programs need a user at the helm to perform interesting operations. Just like the tools that you pick up at the hardware store, a program can be a powerful aid when performing some task. It's important to know how to get input from the user, and how to present them with a way to see how the program is running with the results that are coming back. The basic input and output functions in Python are explained in this chapter, and there's plenty of sample code to help get you started with your own programs.
4 | 5 |We've had an introduction to variables, the building blocks of memory in programming. We've stored our own numbers and strings in them, we've compared them to one another, and we've mixed and matched them in interesting ways. Ultimately though, we're a little bound to the results we type in at that moment. You can't expect every user to learn what a variable is, how types are used in Python, and how to perform variable assignment. Fortunately for us, there are easier ways to get data from users.
8 | 9 |Input and output functions in Python exist so that programmers can speak to users through the code, instead of having to manually enter in data by themselves. We write programs to automate these processes, and we don't want to have to type in every piece of data ourselves. In most cases, we can't even know what the data will be until the moment we run the code.
10 | 11 |If we want to ask the user a question, like "How old are you?" or "What is your name?", we are asking the user for some input. We'd like to pose a question, give a prompt, and wait for the user to enter in the answer. There is a built-in function called input that does exactly this. As a simple example, look at the following code:
14 | 15 |
16 | >>> input("Enter your name: ")
17 | Enter your name:
18 |
19 |
20 | By using the input statement along with a string containing the question you'd like to ask the user, you can get the response you're looking for. In this case, the interpreter is actually waiting for some input from us, and we don't yet see the >>> prompt, because we haven't given our name. Let's finish things up, and type in a name.
21 | 22 |
23 | >>> input("Enter your name: ")
24 | Enter your name: Alexander
25 | 'Alexander'
26 |
27 |
28 | You might be wondering why it just printed out our answer at the end. It's acting in a similar way to our calculator examples by printing out the result of the statement. When we typed in 3 + 4 at the prompt, it printed 7. When we typed in a statement asking for the user's name, it gave us a result in the same way. Here, the result is the string "Alexander", exactly as we typed it in.
29 | 30 |Take a second now to go to your interpreter and type a simple input statement like the one above. You should see some similar output in your own example. The input function prints out your question string to the screen, immediately pauses and waits for you to enter a string that ends as soon as Enter or Return are hit. When it's all done, it gives you back the value at the end.
31 | 32 |So with this knowledge, how can we use input functions in our code? We know that we can use variables to capture the output from a math equation. We can use the same approach with the input function. Since input is a function that returns a result (the string we got from the user), we can use variable assignment like we learned in the previous chapter to capture the response.
33 | 34 |
35 | >>> name = input("Enter your name: ")
36 | Enter your name: Alexander
37 | >>> name
38 | 'Alexander'
39 |
40 | We declare a variable called name, and use it to capture the value that input returns to us. Notice that we didn't get an immediate response with the "Alexander" string from the interpreter once the input completed. It's almost as if adding the variable assignment causes the interpreter to immediately place the value that gets returned from the input function into the variable, whereas omitting the assignment forces it to take the value and dump it onto the screen. The interpreter wants to send the value somewhere. Adding variable assignment gives Python a convenient place to hold the value.
41 | 42 |The input function always returns a string, so how can these functions also be used to get numbers from the user? If you recall, at the end of the last chapter, we learned how strings can be converted into numbers using the int and float built-in functions. By using the same techniques as before, we can convert returned strings from the input function into numbers.
43 | 44 |
45 | >>> age = input("Enter your age: ")
46 | Enter your age: 21
47 | >>> age
48 | '21'
49 | >>> int(age)
50 | 21
51 |
52 |
53 | Even though we get a string back from the input function, our type conversion functions can transform a str value into an int or a float for us. We also don't need to use the str function with input, as the results are already coming back as a string, and we don't gain anything by converting a string into a string.
54 | 55 |Built-in functions and return values can actually be chained together to simplify the creation of variables and the number of lines use in our program. We know that input is a function that returns a value, so we can actually use the input function as input to one of our built-in type conversion functions like int. For example, we can write code like this:
56 | 57 |
58 | >>> age = int(input("Enter your age: "))
59 | Enter your age: 21
60 | >>> age
61 | 21
62 |
63 |
64 | Take a moment to stop and make sure you understand what's happening there, as it might look quite a bit different than what you've seen before! It's equivalent to the following set of instructions:
65 | 66 |
67 | >>> temp = input("Enter your age: ")
68 | Enter your age: 21
69 | >>> age = int(temp)
70 | >>> age
71 | 21
72 |
73 |
74 | We could go through the trouble of defining the temp variable, assigning it the returned string from the input function, and using the new temp variable as input to the int function. It is less work to simply substitute the input statement into the second line as we did in the first example, and to omit the declaration of the temp variable altogether. This is what is meant by chaining the function calls together. We move the input statement right into the int function parameter, because we know that it returns a string for us. So if you need to get a number from the user, like their age, you can use int(input("Question: ")), with the input function call directly in the int function's parameter.
75 | 76 |Each time we use one of the functions like input or int without variable assignment, or when we type in a variable name into the interpreter prompt, it appears as though we're printing out a value. What's really happening though, as we alluded to earlier in the chapter, is that a value is being returned by these functions and dropped to the screen because there's nowhere else to put it. We're not really printing anything for the user, and we don't yet have a way to use these values in a meaningful way. We can't say "Your name is Alexander" yet, or "You are 21 years old", because we don't have a way to output this information in collaboration with the variables we're storing.
79 | 80 |The print built-in function allows us to do all of these things. When you print information, you're telling Python to send some data to the screen for the user to see. It's not printing to a printer, but printing to the available display, like the interpreter window.
81 | 82 |The traditional example for printing has traditionally been to say "Hello world!". Let's try that one now. Type the following into the IDLE window:
83 | 84 |
85 | >>> print("Hello world!")
86 | Hello world!
87 |
88 |
89 | Well, hello yourself! In that single statement, a simple greeting is printed out to the window. Since there are no quotes around the result, you can tell that it's been printed and that it's not just a string being returned. By using the print function, we actually printed our data right to the screen.
90 | 91 |To use variables and other pieces of interesting information, we can add more parameters to the print function when we call it. Let's play around with the name example and see if we can get something a little more complicated.
92 | 93 |>>> name = input("Enter your name: ")
94 | Enter your name: Alexander
95 | >>> print("Hey, it's", name, "-- hello!")
96 | Hey, it's Alexander -- hello!
97 |
98 |
99 | Great! That's pretty different from what we've seen before. It also shows you how to use the variables that have been collected along the way from equations and inputs. We have a dynamic piece of information (the name variable) that we don't know when we're actually writing our program. The user could enter anything for their name, and our code would just handle it in the print statement, regardless of what they'd put in. We can play around with this to show how things really are variable, and how a variable got its name as a container for dynamic memory objects.
100 | 101 |
102 | >>> name = input("Enter your name: ")
103 | Enter your name: a ham sandwich
104 | >>> print("Hey, it's", name, "-- hello!")
105 | Hey, it's a ham sandwich -- hello!
106 |
107 |
108 | The print statement doesn't need to know anything about the contents of the name variable. It just sends it as output to the screen as it would for any other piece of data.
109 | 110 |We aren't restricted to a single parameter in the print function either, as seen in the previous example. We can have long lists of strings or variables, as long as everything is separated by commas. In the print statement above, we have three function parameters. First is the "Hey, it's" string that comes before the actual name in our output. Second is the name variable, and of course Python knows to use the variable because we've omitted quotes from it. Last is the "-- hello!" string that ties everything together in our output.
111 | 112 |One nice thing about the print statement that differs from our math equations is that print can send strings, numbers, and boolean values without any conversion. It already knows how to print a number to the screen by automatically converting it to a string, so you don't have to worry about doing that yourself. For example,
113 | 114 |
115 | >>> name = input("Enter your name: ")
116 | Enter your name: Alexander
117 | >>> age = int(input("Enter your age: "))
118 | Enter your age: 30
119 | >>> print(name, "is", age, "years old.")
120 | Alexander is 30 years old.
121 |
122 |
123 | There is no need to use str(age), although we could have done so, since the print statement tries to convert everything to a string object when it's printing to the screen. This print statement has four parameters, using two variables and two raw string values.
124 | 125 |By default, the print statement adds a space between each of the parameters before printing to the screen. If we wanted our name to be the last word in a sentence, we'd need to change things slightly. For example, the following code doesn't work exactly as we might expect:
126 | 127 |
128 | >>> name = input("Enter your name: ")
129 | Enter your name: Alexander
130 | >>> print("Your name is", name, ".")
131 | Your name is Alexander .
132 |
133 |
134 | The final output has an extra space between name and the period. If you'd like to tell print to forget about the spaces, you can add another parameter to the statement when you call the function. An optional parameter called sep, an abbreviation for separator, is set to a single space by default. When you call print without specifying sep, you're implicitly doing the following:
135 | 136 |
137 | >>> print("Your name is", name, ".", sep=" ")
138 | Your name is Alexander .
139 |
140 |
141 | The sep variable is used internally in print to separate each of the parameters. It's made available if you want to change how the data is sent to the screen. You have the option of setting it to a string with no spaces to format your output in a different way. Note that now we have to actually add a string to the first parameter to make sure we don't lose the separator space that we do want!
142 | 143 |
144 | >>> print("Your name is ", name, ".", sep="")
145 | Your name is Alexander.
146 |
147 |
148 | To show this explicitly, try changing sep to something completely different.
149 | 150 |
151 | >>> print("Your name is", name, ".", sep=":)")
152 | Your name is:)Alexander:).
153 |
154 |
155 | Up until this point, you've probably been relying on the interpreter and the prompt, and typing in each statement one after the other. If you're like me, you've been using the copy and paste functionality of the editor to save yourself from typing things over and over again. And if you're like me, your typing could use some work!
158 | 159 |Fortunately, the IDLE environment offers a very convenient way to store our source code in a reusable way, and to make changes by just editing our program in a file. Python programs are generally stored as text files, only instead of ending in .txt like a typical file, or .doc like a document your word processor might produce, Python files end in .py.
160 | 161 |Go to the IDLE File menu, and click on New Window. You should get another similar window to pop up with a header that reads "Untitled". Go to the File menu in this new untitled window, and click on the Save option. You can save this file anywhere you'd like, but make sure that when you give it a name, you call it something like program.py and not program.txt or just program. Give your file a name that ends in .py so that the IDLE interpreter will know this is a Python file.
162 | 163 |Once you've saved your Python file, try typing in a small program. We'll use a familiar one to start with. Don't be alarmed when you don't see the >>> prompt! By saving our source code in a Python file, we gain the ability to type in many statements at once, along with the ability to run them all one after the other in a full program. Type in the following two lines in your new file:
164 | 165 |
166 | name = input("Enter your name: ")
167 | print("Hi,", name)
168 |
169 |
170 | Make sure you save the file, and once it's ready to go, click on "Run Module" under the Run menu. The original prompt window should pop up, and you should see something like the following:
171 | 172 |
173 | >>> ============================= RESTART =============================
174 | >>>
175 | Enter your name:
176 |
177 |
178 | If you see that, congratulations! You've officially run your first multi-line Python program! It's just like the previous examples where Python code was sent one line at a time to the prompt. In this case, your action of saving the source to a file and running the entire thing has told Python that you've got a more complicated program with multiple lines. You can go ahead and type in your name to observe the results. It runs just like the previous code, but with no need to stop in the middle to manually enter in the print statement.
179 | 180 |With the introduction of unknown input data from the user, you now have the ability to break your programs in ways you might never have considered possible. It's wonderful! Imagine asking the user for some input. Any input will do, really! You might ask them to constrain themselves to numbers, or to names, but input doesn't force them to actually do this. Essentially, we've just opened all sorts of doors for breaking our code in new and interesting ways.
183 | 184 |An important thing to remember is that the values returned by input are always strings. The input statement doesn't know if you're asking for a number. It's your responsibility to convert the string that is always returned from input into the correct type. You can see an example of this in the following code.
185 | 186 |
187 | >>> x = input("Enter a number: ")
188 | Enter a number: 50
189 | >>> x + 60
190 | Traceback (most recent call last):
191 | File "<pyshell#7>", line 1, in <module>
192 | x + 60
193 | TypeError: Can't convert 'int' object to str implicitly
194 |
195 |
196 | There's an exception again. It's a TypeError, so what does that mean? We know that input returns a string, and that it always returns a string. If we try to use the value that is returned by input in an addition statement, the Python interpreter is going to complain enthusiastically. It looks like the values 50 and 60 will be added together to get 110. In reality, you're attempting to add the string "50" and the number 60. These two values are of different types, so Python isn't able to add them together like you might expect. This leads to the TypeError exception, and the warning about int and str objects.
197 | 198 |To make things more complicated, it turns out that Python doesn't always complain when the type of your value is inappropriate. You've seen how you can add float and int numbers together. Technically they're different types, but the language is designed to understand that these values can be treated in similar ways in many instances. There is some support for treating numbers as strings implicitly, as you can see in the following example.
199 | 200 |
201 | >>> input(60)
202 | 60100
203 | '100'
204 |
205 |
206 | What happened there? We passed in the number 60 to input, which expected a string as a parameter. Python was able to infer that the number 60 could be converted to the string "60" and used as the user request string. The second line is made up of our question string ("60"), and our response ("100"), and the returned value is the string "100". It looks a bit strange. Watch out for implicit type conversion!
207 | 208 |You can start to think about this parameter in more general terms, and you are highly encouraged to start being a bit silly. One great way to show what it actually means to return a value from a function is in the following code:
209 | 210 |
211 | >>> input(input("What question should I ask? "))
212 | What question should I ask?
213 |
214 |
215 | Now honestly, what on Earth is that all about? In that code, we've nested a user request string inside of an input statement like we'd normally do. However, we've nested the input statement inside of another input statement! Does this even make sense? Take a second to think about what this code is doing, and try to convince yourself that a statement like this can actually exist.
216 | 217 |The code is actually using the inner input function call to ask the user to provide a question for the outer input function call. We know that input returns a string containing input from the user after asking some question. If we know that to be true, then we can actually place an input statement inside of another one, knowing that the inner nested input will return a string for the outer one to use as a question. Let's rewrite it like this:
218 | 219 |
220 | >>> question = input("What question should I ask? ")
221 | What question should I ask? How old are you?
222 | >>> input(question)
223 | How old are you? 25
224 | '25'
225 |
226 |
227 | It's a lot more readable like this, but the two pieces of code are basically equivalent. If input returns a string, then we can nest it inside of other functions that expect string parameters. With that in mind, we could use the code in the following way:
228 | 229 |
230 | >>> input(input("What question should I ask? "))
231 | What question should I ask? How old are you?
232 | How old are you? 25
233 | '25'
234 |
235 |
236 | You're actually asking the user to provide the question that they want to ask themselves! Crazy stuff.
237 | 238 |What about print? What does print return?
239 | 240 |
241 | >>> input(print("How old are you? "))
242 | How old are you?
243 | None30
244 | '30'
245 |
246 |
247 | What the heck is None? This looks a lot like the previous code, except that we got a strange None value in the middle of our question.
248 | 249 |The print function doesn't return a value like input. When you print something to the screen, nothing is returned. We don't need to return the string that was printed, and we don't need to know if it succeeded or failed to print to the screen. The print function does its job, and we move on with things. If we try to use print to provide a string for input, it actually returns the Python built-in value None. This means that the question that we are asking the user either doesn't exist or is None when converted to a string, and the response ("30") only exists because we saw the result of the print statement on the previous line. It's awfully strange, so you should take a minute to type in that code and play around with it.
250 | 251 |If you'd like to use None, you can assign it to variables just like any other value.
252 | 253 |
254 | >>> x = None
255 | >>> print(x)
256 | None
257 |
258 |
259 | We don't have a lot of use for None right now, but there are lots of good reasons to use it when our programs start getting more complicated. For example, we might ask the user for input, and if we don't like the result, we set the variable to None instead. If we ask them for their age, and they give us a negative value, we set the age variable to None so that we know things went wrong later on in the code.
260 | 261 |A final note about saving your source code: Saving a Python source code file without the .py extension doesn't show colour formatting in some versions of IDLE! If you are working in IDLE and you don't see colours in your source code display, make sure you've saved your file with a .py extension. It doesn't change any of the functionality of your code, but it sure does make it easier to see what you're doing.
262 | 263 |Now that you can write more complicated programs, try adding a few more lines at the end of your new program. Can you add in the age request? What about asking for the user's last name, or their hometown? Can you make your new print statements use old variables, stating things like "Well, Alexander, you appear to be from Kingston," if the name and city correspond to the input you have stored in your variables?
266 | 267 |Try to play around with some other programs in your new Python file. Feel free to save it, and to open a new one so that you don't lose your old programs. It might be helpful to create a particular directory to save everything in so that you don't misplace any of your work.
268 | 269 |1. Write a small series of input and output statements to ask the user some questions you might want answered. In your questionnaire, ask a question that results in a float value, and see how the print statement formats the result.
272 | 273 |2. Make a very simple calculator example. Retrieve two string variables one after another as input from the user, convert them into numbers, and print out the result of adding them together. Try again with other operations like multiplication.
274 | 275 |3. Earlier in this chapter, we played around with placing the input function call directly inside of the int function, so that our returned string value would immediately be converted into a number for us. Review that section, and then type the following line into either the IDLE command prompt or your Python source file:
276 | 277 |
278 | print(input("Enter your name: "))
279 |
280 |
281 | What is this code doing? Can you come up with a two-line example that uses a variable to capture the result from input to accomplish the same thing?
282 | 283 |4. As an example of the reason to add .py at the end of your source code files, try creating a new file inside of the IDLE development environment, and save it with a .txt extension. Type in some Python code, and use the Run Module command. The program should still run, but do you notice any differences that might make it more useful to use a file that ends in .py? In particular, what happens to the colour formatting when you don't save with a .py extension?
284 | 285 |5. In the Breaking Stuff section, we placed a call to input inside of another input function. We also placed a print inside of an input function. What happens when you try an input inside of a print statement?
286 | 287 |
288 | print(input("How old are you? "))
289 |
290 |
291 | What does the output mean? Is a value returned, and why?
292 | -------------------------------------------------------------------------------- /site/section/c3.html: -------------------------------------------------------------------------------- 1 |Variables are references to a part of the program memory, and each variable has a name and an associated value. For example, when you ask someone for their phone number, you probably make an effort to save it somewhere. In the non-programming world, we might write the answer down in an address book on a piece of paper. If you meet me somewhere and ask for my phone number, you might end up with a card that says "Alexander: 555-1234." In many ways, a variable is like one of these pieces of paper, with the name Alexander (or Alexander's phone number), and the value 555-1234. This chapter will help explain how Python's memory system works, and how you can start storing and retrieving your own values effectively.
4 | 5 |When writing code, engaging in conversations with people, or generally going about our lives, we frequently encounter situations where we need to store something away in our memory. If you and I are speaking, you might ask me what my name is. If I answer that my name is Alexander, you'll hopefully tuck that away somewhere in your head. When you see me, you recall that I happen to have the name Alexander. Consider our calculator analogy again, and think about the equations we worked through. We did some simple multiplication, and calculated equations like 3 times 4. On many calculators, you can find a memory key. If you're working through a complicated example, you can store the result of 3 * 4 in the calculator's memory, and you can use the memory recall button to save you the trouble of typing in 3 * 4 each time you want that value.
8 | 9 |A variable name is a way of referencing some value that you've specified an interest in keeping track of to potentially have access to it at a later time. In the example where you asked me what my name is, the variable name is vaguely represented in your head as "That guy's name", and the value associated with that variable is "Alexander". On the calculator, the memory is usually just called M, and if we store the result of 3 * 4 in M, then M is 12.
10 | 11 |Variables are created by using the equals sign. This is called variable assignment (you're assigning a value to a variable), and looks like this:
12 | 13 |
14 | >>> x = 10
15 |
16 |
17 | In this example, Python is asked to create a variable called x, and that the value 10 should be assigned to the new variable. Based on the previous examples, you might be asking where the output is from this statement. After all, we just executed a Python statement, so shouldn't it tell us whether or not it succeeded? In variable assignment, unless you see an error, it's fairly safe to assume that everything worked as planned, and that we've now got a new variable in memory called x that holds the value 10. You can observe this explicitly at the prompt by simply typing in the name of the new variable.
18 | 19 |
20 | >>> x
21 | 10
22 |
23 |
24 | That's pretty interesting. When we write code or evaluate equations, Python knows that when x is used, it should use the value 10 in its place. Now we can do interesting things with our variable in the same way that we did interesting things with numbers. When we looked at multiplication, we asked Python to tell us the result of 3 times 4. Additionally, it was suggested that the memory button on a calculator could hold this value. How do we approach this in Python? Well, what about variables?
25 | 26 |
27 | >>> x * 4
28 | 40
29 |
30 |
31 | Since x has the value 10, the Python interpreter is able to substitute 10 into our equation, calculate that 10 times 4 is 40, and output the result. Remember, a variable has a name that you can reference in your Python code, along with an associated value. You can say that x has the value 10, the author's name has the value "Alexander", and so on.
32 | 33 |Variables can be used to hold the results from more complicated expressions too. If we want to store the result of 3 * 4, we can write the following code:
34 | 35 |
36 | >>> x = 3 * 4
37 | >>> x
38 | 12
39 |
40 |
41 | Note that x doesn't hold the equation 3 times 4, but rather the result of the equation. Does it matter? Well, yes, and it turns out that this is an important distinction to make. The right side of the statement, which in this case is everything after the equals sign, is calculated by Python first. The result of all that calculation is stored in the x variable, and can be accessed later. The variable stores the result of an equation, and not the equation itself. To really show this, let's define a new variable y.
42 | 43 |
44 | >>> x = 3
45 | >>> y = x * 4
46 | >>> y
47 | 12
48 | >>> x = 4
49 | >>> y
50 | 12
51 |
52 |
53 | If it was true that Python was storing the equation in the variable and not the value, the second time that we'd asked for the value in y would have returned 16 instead of 12. (Sanity check: if the variable y held x * 4 instead of 12, setting x to 4 would modify the value in y.) Changing the value of x, used in the initial calculation of y's value, had no effect on y later on in the interpreter.
54 | 55 |Every value in Python, from the number 12 to the name "Alexander", has something called a type. The type of a variable's value indicates whether the value is an integer number, a string, or a more complicated piece of data. This information is important to Python because things can get a bit messy if you start trying to do addition on the number 12 and the string "Alexander". It's not intuitively clear what the result of 12 + "Alexander" is, or if it's even defined at all. (Spoiler: It's not defined, and gives a big error if you try it.. You should try it!)
58 | 59 |All of the previous numbers that we looked at were integers. An integer is a number without a decimal component, so 12 is an integer and 12.5 is not. Python has a type for integer values, called int. It also has a type for numbers that may have decimal components, called float.
60 | 61 |What's a float? The type float is short for floating-point, and describes the system used for keeping track of the decimal point in the internal representation of numbers on a computer. The numbers 123456789 and 0.123456789 have the same significant digits, but have a different decimal point location. The details of how and why this is done are outside the scope of this book, but when you see float used to describe a value's type, think about that floating decimal point, and you'll know what you're dealing with.
62 | 63 |You might be asking yourself why Python goes to the bother of separating out one type of number from another. After all, you can go to the interpreter and type in something like this:
64 | 65 |
66 | >>> 3 + 4.5
67 | 7.5
68 | >>> 3 + 4
69 | 7
70 | >>> 3.5 + 4.5
71 | 8.0
72 |
73 |
74 | One big question that is raised is why Python bothers to distinguish between integer and floating point numbers in the first place. After all, if we can add any two numbers together regardless of their type, what does it matter that one might have a decimal value? The primary reason for this is performance. For now, that's slightly outside the scope of what we need to worry about. You might like to think of it this way. Storing decimal values is a little more complicated than storing integer values with nothing after the decimal point. Even though that's just a little bit of work, when you're dealing with boatloads of numbers, all of that little work starts to add up. And if we're doing the sort of thing that only requires integers--three apples, ten fingers, and so on--then eliminating the need to worry about the decimal value can save of a lot of time.
75 | 76 |We can use a built-in function in Python to give us the actual type of our data, and to explain to readers with a keen-eye why 3 + 4 gives 7, but 3.5 + 4.5 gives 8.0 (notice that there is a decimal in the second case). But what is a function? A function is a separate piece of code somewhere that you can use by calling it, possibly with parameters. As a practical example, there is a function in Python called type, that tells us the type of a value.
77 | 78 |
79 | >>> type(10)
80 | <class 'int'>
81 |
82 |
83 | If we give that statement to the interpreter, asking it to call the type function with the parameter 10, it gives us the answer that 10 is an int. If we try using the type function with a number with a decimal value, we get something like the following.
84 | 85 |
86 | >>> type(10.5)
87 | <class 'float'>
88 |
89 |
90 | It's thanks to the decimal value that the new number has type float and not int. By explicitly adding the decimal point to the number, we are actually telling Python that this is the type of value that might have interesting numbers after the decimal. For practical purposes, it's often enough to know that int and float variables are just numbers, and that int variables have no explicit decimal component, whereas float variables do.
91 | 92 |What about fragments of text, like the "Alexander" example from earlier? We can find out, again by using the type function.
93 | 94 |
95 | >>> type("Alexander")
96 | <class 'str'>
97 |
98 |
99 | In this case, we're dealing with text, and in programming languages, we call that a string (abbreviated to str in the example above).
100 | 101 |You might have noticed that in the Python code, we wrapped the actual string value with double-quotes. You also might have noticed that variables have no quoting. It is necessary to make sure that Python is aware of the difference between input values and variable names. This is done by wrapping the string values inside of quotes like this. We can break Python easily by omitting them:
102 | 103 |
104 | >>> type(Alexander)
105 | Traceback (most recent call last):
106 | File "<pyshell#17>", line 1, in <module>
107 | type(Alexander)
108 | NameError: name 'Alexander' is not defined
109 |
110 |
111 | We got a very specific type of error there. Python is telling us that a name isn't defined, and complains about a NameError. That's Python's way of saying that it expected to find a variable called Alexander. We didn't wrap our expected string in quotes, so Python tried to treat our value as a variable and crashed when it wasn't able to find the variable. When using strings, make sure you remember to add quotes!
112 | 113 |In this book, we're going to try to stick to double-quotes for strings. You can actually use single-quotes, and even triple-quotes, depending on the situation! Here's what our example would look like with a single-quoted string.
114 | 115 |
116 | >>> type('Alexander')
117 | <class 'str'>
118 |
119 |
120 | All of the formats have a reason for being used, but double-quotes are going to save you the most amount of surprising bugs down the road. The reason for this is that there will often be string values like "What's your name?", and if single quotes are used, Python won't be able to tell where one string begins and ends. Take a look at this:
121 | 122 |
123 | >>> x = 'What's your name?'
124 | SyntaxError: invalid syntax
125 |
126 | If you read that, what's to say that the string isn't four characters long, and that the "s your name?" part is just a typo? That's what Python means when it tells you there's a syntax error. It believes something is wrong with the way you've written the code, and that it's not proper Python syntax. Most of the time, it's a quote that's either missing or in a place it shouldn't be. Of course, you can still hit problems if you want double-quotes in your string. We'll get into more detail in the next chapter about how you can solve that problem.
127 | 128 |One more type that we'll run into periodically is the boolean, abbreviated to bool in Python. A boolean is very straightforward: the value is either True, or it's False. There are no numbers, and no decimal points. It either is, or it isn't.
129 | 130 |
131 | >>> True
132 | True
133 | >>> False
134 | False
135 | >>> x = True
136 |
137 |
138 | You'll want to note the fact that the True and False values are capitalized on the first letter, and if you're using IDLE, they'll show up in a different colour. True and False are special terms inside of Python, and we'll be using them to guide our programs through more complicated decisions later on. For example, we can check whether a user is older than a certain age, and if the result is True, do something specific.
139 | 140 |There are a bunch of other types in Python, but for the moment, let's just stick with numbers and strings: int, float, and str. We can do a lot with those, and we'll build up some example code before moving on to bigger examples.
141 | 142 |Many programming languages require you to actually declare a variable before you can assign a value to it. For example, if a variable is going to hold someone's name, it is necessary to declare the variable as one that holds strings, since a name is a string. Python has no such requirement. Python is an untyped language, meaning a variable that's holding an integer can later be asked to hold a string value. Again, other languages may require that a variable that has been declared as a string can only hold strings. Python does not have the same strict rules. What does all of this actually mean? Well, it means that we can do something like this:
143 | 144 |
145 | >>> x = 10
146 | >>> type(x)
147 | <class 'int'>
148 | >>> x
149 | 10
150 | >>> x = "Alexander"
151 | >>> type(x)
152 | <class 'str'>
153 | >>> x
154 | 'Alexander'
155 |
156 |
157 | At first, Python is told to declare a new variable called x, and that x should store the int value 10. We test the type of x, verifying that it is in fact an int, and ask Python what the value of x is. Knowing that x already exists, we overwrite the old value stored in that variable with a new value. We take the variable x that's already been defined, place the new string value "Alexander" in it, and verify the type and value. It's important to note that we didn't destroy x when we did the reassignment, we just gave it a new value. One example is to consider your age as a variable. You don't disappear the moment before your birthday, only to reappear like a phoenix rising from the ashes at the instant you celebrate another year passing by. The value in your age variable just gets increased by one. It's a similar concept in programming. Just change the value inside the variable, forfeit the old one, and keep track of the new one in its place.
158 | 159 |In Python, variable assignment is done by using a single equals sign. Equality also uses the equals sign, but to differentiate between equality and assignment, equality checks use a double-equals sign. Take a look at the code below to see what this means:
162 | 163 |
164 | >>> x = 1
165 | >>> x
166 | 1
167 | >>> x == 1
168 | True
169 |
170 |
171 | The first line defines a variable called x, and tells the new variable x to hold the int value 1. If we want to test whether or not this assignment worked properly, we use the double-equals sign, which reads as "Is it true that variable x is equal to 1?" If the equality statement is True, Python returns the boolean value True. If we give perform another equality check with a value that we know to be different, the equality test should return the boolean value False.
172 | 173 |
174 | >>> x
175 | 1
176 | >>> x == 2
177 | False
178 |
179 |
180 | The same double-equals sign can be used to test the equality of numbers and strings. For example, some fairly obvious tests between values of the same type can be made. We can perform tests to see if int and float numbers retain their equality across types. This is a way of asking whether Python thinks that 2 is equal to 2.0.
181 | 182 |
183 | >>> 1 == 2
184 | False
185 | >>> 1 == 1
186 | True
187 | >>> 2 == 2.0
188 | True
189 | >>> 1 == 1.5
190 | False
191 |
192 |
193 | In the third example above, we do the comparison of the int value 2 against the float value 2.0. Intuitively, these two values are equal, and fortunately for us, Python agrees. If an int and float represent the same exact number, the equality test will return True.
194 | 195 |The same symbol can be used to test the equality of strings.
196 | 197 |
198 | >>> "Alexander" == "Alexander"
199 | True
200 | >>> "Alexander" == "alexandER"
201 | False
202 |
203 |
204 | Equality of a string is dependent on the capitalization of the two strings being compared. In the example above, even though the same name was used, the capitalization of the first letter affected the overall equality of the string. Two strings are equal only if all the individual characters in the string are equal. The quotes used have no effect on the strings.
205 | 206 |
207 | >>> "Alexander" == 'Alexander'
208 | True
209 |
210 |
211 | In addition to basic equality testing, Python also allows for the ordered comparison of variables and values to determine if something is larger or smaller than something else. The greater-than and less-than signs can tell you how one value is different from another. A not-equals operator also exists to tell you if a value is different from the source.
212 | 213 |
214 | >>> 1 > 2
215 | False
216 | >>> 1 < 2
217 | True
218 | >>> 1 != 2
219 | True
220 |
221 |
222 | Symbols like the greater-than and less-than signs should be familiar to you. Just like the plus sign and the equals sign, many of these symbols are taken straight out of mathematics. What might be new is the exclamation-mark glued on to the beginning of the equals sign. When you see the != symbol, read it as not-equal-to. You can expect a boolean value to be returned based on whether or not the two values on either side are equal to each other.
223 | 224 |We know that Python treats numbers and strings differently, and even treats different kinds of numbers differently from one another. But what does it mean to have a string with a number in it? If we have the string "1", is it the same as the int 1, the float 1.0, both, or neither? It's possible to test things like this by using equality tests.
227 | 228 |Look at the following familiar example that identifies the types of two sample numbers and compares the equality of those numbers.
229 | 230 |
231 | >>> type(1)
232 | <class 'int'>
233 | >>> type(1.0)
234 | <class 'float'>
235 | >>> 1 == 1.0
236 | True
237 |
238 |
239 | You're already familiar with type, one of the built-in functions in Python. It's time to introduce a few more.
240 | 241 |It's clear now that 1 is a value of type int, and 1.0 is a value of type float. You might also be comforted to see that the same number represented as either an int or a float is treated as being equal. Python allows you to actually convert between int and float values by using the appropriately named int and float built-in functions. They work in a similar way to type by accepting a parameter, such as a number or other value, and then returning the value in the type you request.
242 | 243 |
244 | >>> int(1.0)
245 | 1
246 | >>> float(1)
247 | 1.0
248 |
249 | The first example is a conversion from 1.0, a float value, into the equivalent int value, which comes out as 1. The second example takes the int value 1, converts it into a float, and returns 1.0. When you see the built-in functions like this, it might help to read it out in a full sentence until you're comfortable with the code. The first example says "Give me the integer representation of the value 1.0," and the second says "Give me the floating-point representation of the value 1."
250 | 251 |A nice bonus of the int function is the ability to round numbers down to the nearest integer. It is possible to convert a float into an int, even if the float value has non-zero decimal digits. Converting from type float to type int strips away the decimal component and rounds down. The values that are returned from functions can also be captured in variables, so if we wanted to store the int value of our float with the value 5.9, we treat it like any other variable assignment.
252 | 253 |
254 | >>> int(5.9)
255 | 5
256 | >>> x = int(5.9)
257 | >>> x
258 | 5
259 |
260 |
261 | The same concepts apply to string values, but we have to be a little more careful. The corresponding string conversion function is called str, just like the type name that we discovered earlier, and it accepts a single parameter. Any int or float can be converted into a string. When moving from strings to numbers, however, Python will attempt to convert any string that looks like a number into a numeric representation, but it will fail if the string is a word or some other non-numeric value. If you think about it, every number can be stored as a string, but not every string can be stored as a number.
262 | 263 |
264 | >>> int("1")
265 | 1
266 | >>> float("1")
267 | 1.0
268 | >>> str(1)
269 | '1'
270 | >>> str(1.0)
271 | '1.0'
272 |
273 |
274 | As you can see in the example above, when we call the str function with a numeric value, it gives you a string (with quotes, as expected -- don't forget to look for the quotes!). When we pass the string "1" into either the int or float built-in functions, Python attempts to convert the string into the related numeric value for that type, and returns the value when it's successful. It's pretty good, but it's certainly not perfect.
275 | 276 |
277 | >>> int("one")
278 | Traceback (most recent call last):
279 | File "<pyshell#5>", line 1, in <module>
280 | int("one")
281 | ValueError: invalid literal for int() with base 10: 'one'
282 |
283 |
284 | One great way to break your interpreter is to pick a variable name that already has some predefined meaning in Python. In Python, function names and type names are really just variable identifiers. It just happens that those names point to functions or to types instead of numbers or strings. This might sound a little strange, so let's work by example.
287 | 288 |
289 | >>> int
290 | <class 'int'>
291 | >>> type(int)
292 | <class 'type'>
293 |
294 |
295 | Instead of taking the type of an integer value like 2, we actually took the type of the integer type itself. We can use a few more examples to show what this really means.
296 | 297 |
298 | >>> type(int)
299 | <class 'type'>
300 | >>> type(float)
301 | <class 'type'>
302 | >>> type(str)
303 | <class 'type'>
304 |
305 |
306 | We know that variables in Python have an associated type. If you think of all of the different types that a value can have, that set of types is itself a type. An int is a kind of type, and a str is a kind of type.
307 | 308 |What happens if we want to declare a variable with the name int? We've already got something defined in the environment called int, so what will Python do if we declare something new? You can do this easily with other variables like x, so what does it mean to use int?
309 | 310 |
311 | >>> int
312 | <class 'int'>
313 | >>> int = 2
314 | >>> int
315 | 2
316 | >>> type(int)
317 | <class 'int'>
318 |
319 |
320 | Well, it's nice that we were able to declare a variable called int. Python certainly didn't complain about what we were doing, and it doesn't look like we broke anything right away by doing that. It's a pretty serious problem though. Once we do this, we can't use the int function anymore!
321 | 322 |
323 | >>> int(5.0)
324 | Traceback (most recent call last):
325 | File "<pyshell#15>", line 1, in <module>
326 | int(5.0)
327 | TypeError: 'int' object is not callable
328 |
329 |
330 | Whoops! We actually took the function that int was referring to and removed the connection to the int variable name. The TypeError is telling us that int is no longer a function, and that we can't pass parameters to it like we used to. We redefined int as an actual number, so all of the functionality that was built in before is now gone.
331 | 332 |Any of the names in the Python environment can be used in this way, so you can start to get some really strange results by using them.
333 | 334 |
335 | >>> int(1.0)
336 | 1
337 | >>> int = str
338 | >>> int(1.0)
339 | '1.0'
340 |
341 |
342 | Pretty wild, huh? This is important to know though, especially when you accidentally use a name for your variable that you expect to be something else. If you want to break your Python environment, choose names like int, str, or type for your variables. If not, choose unique names for your variables!
343 | 344 |If you do accidentally overwrite a function that Python uses, you have a few techniques for restoring things to their natural state. The easiest option is to just quit and restart the IDLE interpreter. Any changes you make are temporary, so restarting the Python environment will return things to normal. You can also restore things inside of IDLE by going to the Shell menu and choosing Restart Shell. You'll see a large RESTART message, followed by a new prompt.
345 | 346 |
347 | >>> int
348 | <class 'int'>
349 | >>> int = str
350 | >>> int
351 | <class 'str'>
352 | >>> ============================ RESTART ============================
353 | >>> int
354 | <class 'int'>
355 |
356 |
357 | This is one of the main reasons to be comfortable when breaking things in Python. If you break something, from simple things like adding incorrect types to renaming core functions, you can always restore the environment with a few mouse clicks.
358 | 359 |A variable is a reference to a value. In a programming language, the collection of variables constitutes the program state, or the program memory. In Python, a variable is not restricted to holding values of a particular type. However, each value has a particular type associated with it. Values and variables can be tested for equality, and the type of the value has meaning when checking if two pieces of data are equal to one another.
362 | 363 |Try defining some new variables and see what happens when you modify them through addition or multiplication. See if you can get comfortable with variable creation, and the differences between types. While you're working with these, try assigning variables to other variables.
364 | 365 |1. Define a variable in Python called name, and assign your name to it. Try making it fairly long by using your full name.
368 | 369 |2. Using some of the simple math operations in Python like addition and multiplication, try seeing what happens when you mix an int and a float up in an expression. What happens if you add an int to a float, like 5 plus 10.4? What is the type of the result?
370 | 371 |3. Create two variables, each with numbers stored in them. Use these two variables in a math expression. Say you've defined x and y, what happens if you type x + y in IDLE?
372 | 373 |4. Convert between int and float types for several numbers with and without decimal values.
374 | 375 |5. Play around with converting strings to and from number types. What happens when you try to convert a string like "Alexander" into a number?
376 | -------------------------------------------------------------------------------- /site/section/c7.html: -------------------------------------------------------------------------------- 1 |As we saw in the last chapter, an if-statement is an incredibly useful programming tool. However, one of the problems with an if-statement is that it is still essentially just a one-time operation. For example, in our password program, it would be nice to return back to the top to ask the user again and again until they either gave up or got it right.
4 | 5 |Loops have the same type of functionality as if-statements, but they repeat until you tell them to end. In the password example, when the user's password is entered incorrectly, instead of just ending, a loop could return back to the input statement and start again. We gain a lot of power from this new statement, and this chapter will explain how Python implements it.
6 | 7 |The idea of testing for a necessary condition before executing some code is a fundamental part of computer programming. It is impractical to write useful code that doesn't depend on the input it receives. The input may be strings of text from the prompt, files on a hard drive, or incoming data from the internet. Regardless of the context, checks need to be performed against the values of the variables, and programs get directed to the appropriate path when certain preconditions are satisfied.
10 | 11 |With the examples that we saw in the previous chapter, we have gained the ability to route the user through several paths based on their input. Unfortunately, there are still some limitations. Say that a user enters a number outside the valid range, like a negative integer value for their age. The ideal program would realize that the age was invalid, and simply ask them again. For example, we're not turned away from a friend when we tell them that we're negative five years old (well, I suppose that it depends on the friend). So why should our program end when it reaches an invalid value when we could simply ask again?
12 | 13 |One solution is to check to see if the user gave us a bad value first, and ask them again if they broke the rules. An example from the previous chapter can be expanded in the following way.
14 | 15 |
16 | age = int(input("Enter your age: "))
17 | if age < 0 or age > 150:
18 | print("I think you're trying to trick me.")
19 | age = int(input("Enter your age: "))
20 | print("Alright, you're {0} years old.".format(age))
21 |
22 | Enter your age: -5
23 | I think you're trying to trick me.
24 | Enter your age: 30
25 | Alright, you're 30 years old.
26 |
27 |
28 | It looks good at first glance. But this doesn't really solve our problem, because the user can lie a second time and trick our program again.
29 | 30 |
31 | Enter your age: -5
32 | I think you're trying to trick me.
33 | Enter your age: -5
34 | Alright, you're -5 years old.
35 |
36 |
37 | So how do we get around this problem? We can't just keep embedding input statements inside of if-statements again and again. ... Can we?
38 | 39 |
40 | age = int(input("Enter your age: "))
41 | if age < 0 or age > 150:
42 | print("I think you're trying to trick me.")
43 | age = int(input("Enter your age: "))
44 | if age < 0 or age > 150:
45 | print("I think you're trying to trick me.")
46 | age = int(input("Enter your age: "))
47 | if age < 0 or age > 150:
48 | print("I think you're trying to trick me.")
49 | age = int(input("Enter your age: "))
50 | if age < 0 or age > 150:
51 | print("I think you're trying to trick me.")
52 | age = int(input("Enter your age: "))
53 | # hmm.. again?
54 | print("Alright, you're {0} years old.".format(age))
55 |
56 |
57 | Eventually we're going to hit the limit of our copy-paste ninjitsu, and a troublesome user is going to be able to convince our program that they're negative five years old. What we need is a more robust solution. How about the while statement?
58 | 59 |
60 | age = int(input("Enter your age: "))
61 | while age < 0 or age > 150:
62 | print("I think you're trying to trick me.")
63 | age = int(input("Enter your age: "))
64 | print("Alright, you're {0} years old.".format(age))
65 |
66 | Enter your age: -5
67 | I think you're trying to trick me.
68 | Enter your age: -5
69 | I think you're trying to trick me.
70 | Enter your age: -5
71 | I think you're trying to trick me.
72 | Enter your age: -5
73 | I think you're trying to trick me.
74 | Enter your age: -5
75 | I think you're trying to trick me.
76 | Enter your age: 30
77 | Alright, you're 30 years old.
78 |
79 |
80 | The while keyword works like an if-statement and performs the necessary check to see if the inner block of code needs to be executed. The major difference is that when Python reaches the end of that block of code, it does the expression check again. If the check still returns False, the while loop goes back to the beginning of the block and runs it again and again until things in the expression eventually settle.
81 | 82 |Let's rework the password example from the previous chapter using a loop. Here's the new code.
83 | 84 |password = "spam"
85 | done = False
86 | while done == False:
87 | user_password = input("Enter the password: ")
88 | if password == user_password:
89 | done = True
90 | else:
91 | print("That's not the password! I can't let you in.")
92 | print("SECRET ACCESS GRANTED.")
93 |
94 | Enter the password: turkey
95 | That's not the password! I can't let you in.
96 | Enter the password: spam
97 | SECRET ACCESS GRANTED.
98 |
99 |
100 | The code adds a new loop, along with a boolean variable called done that is initialized to False. The done variable will only get set to True when the password entered by the user matches the one defined at the start of the program. If the password doesn't match, we print out the same old error message. If they do match, the loop will terminate because done is no longer False, and our secret message and other hidden program code will start to execute.
101 | 102 |In the age example above, we have a really clear example of looping that only occurs when necessary. What happens when the user actually enters in a good value the first time instead of entering some invalid negative age that doesn't pass the expression test? In that case, the while loop never enters into the block that asks the user for their age again. The input was acceptable, and we move right past the indented block to the print statement below. The while loop only gets triggered when the data is invalid, and only stays active when the input remains unacceptable.
103 | 104 |This type of example can be augmented with counter variables. These are standard variables that are increased based on the number of times a certain type of input has occurred. (Okay, it's really just an int that we increase by 1 every time something interesting happens. I'm just going to call it a counter variable here.) Let's change the above example slightly to add a counter variable that checks how many times the user has been difficult.
105 | 106 |
107 | age = int(input("Enter your age: "))
108 | counter = 1
109 | while age < 0 or age > 150:
110 | print("That was input #{0}, and you tried to trick me.".format(counter))
111 | age = int(input("Enter your age: "))
112 | counter = counter + 1
113 | print("Alright, you're {0} years old.".format(age))
114 | print("Number of times that I had to ask you: {0}".format(counter))
115 |
116 | Enter your age: 30
117 | Alright, you're 30 years old.
118 | Number of times that I had to ask you: 1
119 |
120 | Enter your age: -5
121 | That was input #1, and you tried to trick me.
122 | Enter your age: -4
123 | That was input #2, and you tried to trick me.
124 | Enter your age: -7
125 | That was input #3, and you tried to trick me.
126 | Enter your age: 30
127 | Alright, you're 30 years old.
128 | Number of times that I had to ask you: 4
129 |
130 |
131 | The addition of a counter provides a visual indication about how many times the loop was executed, and in a sense, actually helps show how the loop is actually working. At first, the counter is set to a starting value of 1 to match the number of times we've presented the input statement to the user and asked them for their age. If they give an acceptable value, we're happy, and the counter never changes. However, the first time that a loop hits an error condition, defined in the code as one that causes the expression in the while-statement to evaluate to True, our counter gets incremented by one.
132 | 133 |It is also interesting to note that the while loop never uses the counter variable in its expression. It's an extra variable that is used for information, and something that changes inside the loop block itself but never gets tested in the loop expression.
134 | 135 |Let's say that we hit a case where the user has lied ten times in a row. We might get suspicious, and we might even think that the user is never going to tell us the truth. If that happens, we'll end up stuck inside our loop forever, never to return to normal program execution. How can we get out of this tricky situation?
138 | 139 |Loops are pretty neat. They give us the ability to run for an arbitrary amount of time, processing data and collecting input until we hit some programmer-defined stopping point. If we have invalid ages, it's possible to keep forcing the user to give new data until they finally comply and give up their actual age. However, we might have edge cases where it would be better to end the loop early, or even to just stop the current execution and move on to the next iteration of the loop itself. If we ever hit a point in a loop where we'd like to break out for some reason, Python provides a couple of handy statements to allow us to do this.
140 | 141 |
142 | age = int(input("Enter your age: "))
143 | counter = 1
144 | while age < 0 or age > 150:
145 | print("That was input #{0}, and you tried to trick me.".format(counter))
146 | age = int(input("Enter your age: "))
147 | counter = counter + 1
148 | if counter >= 5:
149 | age = 0
150 | break
151 | print("Number of times that I had to ask you: {0}".format(counter))
152 | if age == 0:
153 | print("You didn't follow the rules, and I am sad.")
154 | else:
155 | print("Alright, you're {0} years old.".format(age))
156 |
157 | Enter your age: -5
158 | That was input #1, and you tried to trick me.
159 | Enter your age: -4
160 | That was input #2, and you tried to trick me.
161 | Enter your age: -3
162 | That was input #3, and you tried to trick me.
163 | Enter your age: -2
164 | That was input #4, and you tried to trick me.
165 | Enter your age: -1
166 | Number of times that I had to ask you: 5
167 | You didn't follow the rules, and I am sad.
168 |
169 |
170 | In the example above, a condition is set up to make sure that a user who is intent on giving bad data can't succeed in hogging all of the program time. If they give five bad values, we assume they're playing games and get out of there using the break statement. When you break out of a loop, you tell the loop that there's no need to keep testing for the truth condition, and that you're satisfied with the state of the code. By using break, the loop terminates right there, and the rest of the program after the loop starts running.
171 | 172 |Let's use a simple example to just show break on its own.
173 | 174 |
175 | i = 1
176 | while i > 0:
177 | print(i)
178 | i = i + 1
179 | if i > 5:
180 | break
181 |
182 | 1
183 | 2
184 | 3
185 | 4
186 | 5
187 |
188 |
189 | Exiting out of the loop isn't the only action that might be needed. We might also want to stop execution of the current loop block while remaining in the current loop itself. This is different than break, which halts the loop entirely. Here's an example that shows the difference between the two.
190 | 191 |
192 | while True:
193 | num = int(input("Enter a positive number, or 0 to quit: "))
194 | if num < 0:
195 | print("Positive numbers only, please!")
196 | continue
197 | elif num == 0:
198 | print("OK, quitting!")
199 | break
200 | num_squared = num * num
201 | print("{0} times {0} is {1}.".format(num, num_squared))
202 | print("All done!")
203 |
204 | Enter a positive number, or 0 to quit: -1
205 | Positive numbers only, please!
206 | Enter a positive number, or 0 to quit: 3
207 | 3 times 3 is 9.
208 | Enter a positive number, or 0 to quit: 5
209 | 5 times 5 is 25.
210 | Enter a positive number, or 0 to quit: -4
211 | Positive numbers only, please!
212 | Enter a positive number, or 0 to quit: 0
213 | OK, quitting!
214 | All done!
215 |
216 |
217 | We want to get a number from the user so that we can give them the square of that number. In this example, we're only asking for positive numbers, so if the user gives us a negative one, we don't want to quit, but we don't want to actually give them the square. We asked for a positive number, and we'd like to enforce that without quitting in the case of invalid input.
218 | 219 |The continue statement acts like the break statement in the context of the current iteration of the loop. Continuing out of a block of code inside a loop will end the current iteration, return to the top of the loop, and continue from the start of the loop again. Breaking out of a block of code ends the loop altogether.
220 | 221 |To make sure that the loop runs until we actually tell it to stop, we use an expression that might be a little counter-intuitive at first glance. What does it mean to have a while loop that uses the True expression? Look at an if-statement for an example.
222 | 223 |
224 | if True:
225 | print("Hello, world!")
226 | else:
227 | print("Goodbye.")
228 |
229 | Hello, world!
230 |
231 |
232 | Of course it must always be the case that "Hello, world!" gets printed and that "Goodbye." is never seen. By definition, if the if-statement expression evaluates to True, we run the code in the if-statement's code block. True is always True, and True is never False, so it's impossible for us to get to the "Goodbye." print statement. However, when blocks of code are repeating, like with while loops, Python is asked to run the code forever until explicitly told to stop.
233 | 234 |
235 | while True:
236 | print("Hello, world!")
237 |
238 | Hello, world!
239 | Hello, world!
240 | Hello, world!
241 | Hello, world!
242 | [repeat forever..]
243 |
244 |
245 | With break and continue, you gain the ability to write loops that grant you a greater level of control. You aren't bound to just allow the loops to run as they see fit. You have the power to either terminate the entire loop, or to simply terminate the current iteration in the loop by moving to the next one.
246 | 247 |Let's build an example with a counter variable.
248 | 249 |
250 | counter = 1
251 | while True:
252 | print("Hello, world!")
253 | counter = counter + 1
254 | if counter > 5:
255 | break
256 |
257 | Hello, world!
258 | Hello, world!
259 | Hello, world!
260 | Hello, world!
261 | Hello, world!
262 |
263 |
264 | This example still uses the True expression, asking Python to run forever until we tell it otherwise. With the break statement, the kill command is given to the while loop. Based on the number of times we've already printed our statement, we can ask Python to cut the loop short and continue on with the rest of the program code.
265 | 266 |A for statement differs from a while statement by actually requiring a set of elements that it will iterate over. For example, we might want a loop that runs over a range of numbers, like the integer values from 1 to 10. It is possible to set up a counter with a while loop to make this happen, but the for statement is set up to handle this type of situation easily and efficiently. Let's revisit the "Hello, world!" example from the previous section. To see how it can be modified to print out the string five times using a for loop. To do that, we'll learn about a new built-in function called range.
269 | 270 |
271 | for x in range(5):
272 | print("Hello, world!")
273 |
274 | Hello, world!
275 | Hello, world!
276 | Hello, world!
277 | Hello, world!
278 | Hello, world!
279 |
280 |
281 | The range function provides a way to access a set of numbers in an efficient way. When used with a for statement, it performs a loop that runs a fixed number of times. The example above asks Python to run the "Hello, world!" print statement five times. It does this by assigning the new variable x a particular value in the requested range for each iteration of the loop. If you remember how these indices are calculated with string character positions, you'll recall that these indices start at zero. To show this, look at the following code:
282 | 283 |
284 | for x in range(5):
285 | print("The value of x is {0}.".format(x))
286 |
287 | The value of x is 0.
288 | The value of x is 1.
289 | The value of x is 2.
290 | The value of x is 3.
291 | The value of x is 4.
292 |
293 |
294 | When the for function is combined with the range built-in function, each iteration of the loop sets x to the next value in the range we requested. It's as if we had a counter with a while loop that we were manually requesting. The for loop takes the next value automatically, sets the variable x to the new value, and executes the inner code block. With a while loop, the code might look like this:
295 | 296 |
297 | x = 0
298 | while x < 5:
299 | print("The value of x is {0}.".format(x))
300 | x = x + 1
301 |
302 | The value of x is 0.
303 | The value of x is 1.
304 | The value of x is 2.
305 | The value of x is 3.
306 | The value of x is 4.
307 |
308 |
309 | Since the range value gives us this counter behaviour implicitly, we can write code that is a little more readable by combining for and range when the actual number range is known. It is important to note that range(5) gives the first five numbers in the range, starting at 0, and that this range doesn't include the actual number 5. This is a side-effect of the zero-based counting system.
310 | 311 |The range function is versatile enough to allow ranges that don't actually start at zero (for example, the numbers from 2 to 4), and ranges that increase or decrease in other ways than incrementing by one. If we wanted to calculate the squares of the first five positive integers, we could specify the starting and ending values in range and use a similar for loop to get our code. In this case, we can use range(1, 6). As mentioned earlier, we must consider that the end point that is given is never part of the actual range returned. In the range(5) example, the value 5 is never part of the range, and when we use range(1, 6), the value 6 is never part of the range. The ending value is the stopping condition, the value that we stop the range at and never test.
312 | 313 |
314 | for x in range(1, 6):
315 | print("The square of {0} is {1}.".format(x, x * x))
316 |
317 | The square of 1 is 1.
318 | The square of 2 is 4.
319 | The square of 3 is 9.
320 | The square of 4 is 16.
321 | The square of 5 is 25.
322 |
323 |
324 | If a starting value is provided, you also have the option of providing a step value. The step is the amount that the value is modified by at each iteration of the loop. For example, if you want to consider the even numbers instead of every one along the way, you specify a starting value of 0 and a step of 2.
325 | 326 |
327 | for x in range(0, 11, 2):
328 | print("The square of {0} is {1}.".format(x, x * x))
329 |
330 | The square of 0 is 0.
331 | The square of 2 is 4.
332 | The square of 4 is 16.
333 | The square of 6 is 36.
334 | The square of 8 is 64.
335 | The square of 10 is 100.
336 |
337 |
338 | In general, a for statement can be thought of as a way to define a new variable that is given a set of possible values to exist with in the context of a particular block of code. The squares example has some very general code to output the original variable and its square, and the code makes no assumption on what the variable is, except for the fact that it must be a number. We didn't change the inner block between the range(1, 6) and range(0, 11, 2) examples at all. All that was modified was the range that the code was iterated over. Even the variable name remained the same.
339 | 340 |We can use variables in the range function as well. The squares example can be extended to use a user-provided range of numbers to output.
341 | 342 |
343 | lower = int(input("Enter the lower value of the range: "))
344 | upper = int(input("Enter the upper value of the range: "))
345 | for x in range(lower, upper):
346 | print("The square of {0} is {1}.".format(x, x * x))
347 |
348 | Enter the lower value of the range: 8
349 | Enter the upper value of the range: 14
350 | The square of 8 is 64.
351 | The square of 9 is 81.
352 | The square of 10 is 100.
353 | The square of 11 is 121.
354 | The square of 12 is 144.
355 | The square of 13 is 169.
356 |
357 |
358 | Neat trick, eh? Give it a shot! What happens if you enter some different numbers, or if you start with the larger number instead of the smaller one? Can you break this code?
359 | 360 |One powerful technique using loops involves nesting them inside of other loops. If you have two pieces of data that are changing in relation to one another, you can define a new loop inside of the original loop to process your data. Let's use multiplication tables as an example of this.
363 | 364 |
365 | for x in range(1, 6):
366 | for y in range(1, 6):
367 | print("{0} * {1} is {2}".format(x, y, x * y))
368 |
369 | 1 * 1 is 1
370 | 1 * 2 is 2
371 | 1 * 3 is 3
372 | 1 * 4 is 4
373 | 1 * 5 is 5
374 | 2 * 1 is 2
375 | 2 * 2 is 4
376 | [...]
377 | 5 * 3 is 15
378 | 5 * 4 is 20
379 | 5 * 5 is 25
380 |
381 |
382 | What happened in this example? The for loop using the y variable is sitting inside of the for loop using the x variable. Every time the x loop happens, five iterations of the y loop occur. At first, x is set to 1, and y is set to 1. When the print statement finishes, the y block also finishes, and the next iteration of the y loop begins. This bumps up the y value to 2, while x remains at 1, and the print statement occurs again. Once the print statement finishes showing the result of 1 * 5, the y loop is finished, and the first x block finally finishes. The x variable jumps up to 2, and the y loop starts all over again with y set to 1. The important note there is that the entire y loop is essentially refreshed each time the x loop starts.
383 | 384 |Let's use some print statements to provide a clearer example of the way that inner loops actually evaluate in the code.
385 | 386 |
387 | for x in range(3):
388 | print("x: {0}".format(x))
389 | for y in range(3):
390 | print(" y: {0}".format(y))
391 |
392 | x: 0
393 | y: 0
394 | y: 1
395 | y: 2
396 | x: 1
397 | y: 0
398 | y: 1
399 | y: 2
400 | x: 2
401 | y: 0
402 | y: 1
403 | y: 2
404 |
405 |
406 | The inner loop runs multiple times, and each time the y loop starts up, it has a different value for x. You can use this to build complicated examples with different data sets. When we look at list variables in the next chapter, you'll see how you can combine things like sets of names, locations, or other variables in ways like this.
407 | 408 |Want to know one of my favourite ways of breaking stuff? Or, at least, one of the ways that I most frequently break stuff? It's a little bit embarassing, but it happens all the time, so I might as well fess up to it.
411 | 412 |In Python, as in many other programming languages, variable names are important. You should think very carefully about the names you use, both in how they're capitalized, what information they convey, and in the styles of names used for particular purposes. Case in point: loops are often written using the identifier i. Why i? Well, just because. And if i is taken in one of the outer loops, just use j. Lots of loops will default to i or j, just as many simple variables will default to x.
413 | 414 |Where we get bit by this is when we forget about the variables that have already been defined, and we reuse them in some context. Let's look at a simple, and perfectly obvious example, of a broken piece of code.
415 | 416 |
417 | for int in range(10):
418 | print("{0} times {0} is {1}.".format(int, int * int))
419 |
420 | 0 times 0 is 0.
421 | 1 times 1 is 1.
422 | 2 times 2 is 4.
423 | 3 times 3 is 9.
424 | 4 times 4 is 16.
425 | 5 times 5 is 25.
426 | 6 times 6 is 36.
427 | 7 times 7 is 49.
428 | 8 times 8 is 64.
429 | 9 times 9 is 81.
430 |
431 |
432 | Seems legit, right? We define a variable called int and call the range function to give us 10 different values, each of which is assigned to int and used to print out a string showing what the square of the value is. The code even seems to do the right thing, and ends without any errors.
433 | 434 |What matters in this piece of code is the assignment to int. The int identifier is currently assigned to a function--in this case, the function that converts another value into an integer. If we assign a new value to int, we actually tell Python to throw away the reference to the function that converts values into integers, and to instead track the value returned by range. For example, look at this code:
435 | 436 |
437 | for int in range(10):
438 | print("{0} times {0} is {1}.".format(int, int * int))
439 |
440 | x = int(input("How high should I go? "))
441 |
442 | for int in range(x):
443 | print("{0} times {0} is {1}.".format(int, int * int))
444 |
445 |
446 | That code should, at first glance, show us the squares of the values from 0 to 9, then ask us what value we should pass to range, and then do the same thing. The int call, when used with input has previously converted string representations of numbers into the actual number value itself. However, by telling Python that int--the identifier int, which is a variable name--is used to store a value now, we can no longer use it to access the function!
447 | 448 |
449 | 0 times 0 is 0.
450 | 1 times 1 is 1.
451 | 2 times 2 is 4.
452 | 3 times 3 is 9.
453 | 4 times 4 is 16.
454 | 5 times 5 is 25.
455 | 6 times 6 is 36.
456 | 7 times 7 is 49.
457 | 8 times 8 is 64.
458 | 9 times 9 is 81.
459 | How high should I go? 15
460 | Traceback (most recent call last):
461 | File "sample.py", line 4, in <module>
462 | x = int(input("How high should I go? "))
463 | TypeError: 'int' object is not callable
464 |
465 |
466 | We'll get into more detail about why this happens later, don't worry. For the time being, try not to reuse identifiers. You might not get what you expect.
467 | 468 |Loops are a fundamental part of programming. Adding control flow gives your program the flexibility to run sections of code multiple times, and allows your code to perform complicated tasks that are otherwise impossible or unwieldy.
471 | 472 |In the next section, we'll look at a data structure called a list that is used by Python to enable some very diverse functionality.
473 | 474 |1. Write a program that prints all the multiples of 7 from 0 to 100. Experiment with printing the squares, the reciprocal (one divided by the number), and other expressions.
477 | 478 |2. Print out the multiplication tables from 1 to 10 in a table on the screen. You can use the end parameter in print statements to stop Python from printing each string on its own line. For example,
479 | 480 |
481 | for x in range(1, 11):
482 | print("{0:4}".format(x), end="")
483 |
484 | 1 2 3 4 5 6 7 8 9 10
485 |
486 |
487 | Set up an outer loop and an inner loop to keep track of the values you're multiplying together, and let each row and column correspond to increasing values from 1 to 10.
488 | --------------------------------------------------------------------------------