:tocdepth: 2 .. _user_input: ****************************************************** User input ****************************************************** .. contents:: :local: .. highlight:: python Get user input ========================================================================== We have discussed assigning values to variables that are evaluated from expressions. But what if we want the user (including ourselves) to be able to enter some information from the keyboard? Well, Python provides a built-in ``input()`` function for prompting and receiving information. Let's take a look at the function's help, or **documentation string** (**docstring**), with ``input?``. We will look more deeply at some of the specific syntax of docstrings in :ref:`another section shortly `, but let us interpret what we can here. In Python, we can typically see the help docstring by putting a ``?`` after the function's name. Here, the output of ``input?`` (with my version of Python; it can vary) looks like: .. code-block:: none :linenos: Signature: input(prompt=None, /) Docstring: Read a string from standard input. The trailing newline is stripped. The prompt string, if given, is printed to standard output without a trailing newline before reading input. If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError. On *nix systems, readline is used if available. Type: builtin_function_or_method From the first sentence in Line 3, we note that this function will always "read a string" from the input. So, whether we type ``hello`` or ``4``, Python will read it in as a string, i.e., ``'hello'`` or ``'4'``. Basically, Python doesn't want to try to guess what we are entering. This is OK, because *we* can decide what to do with the entered string, because we have functions that can convert type. .. container:: qpractice **Q:** Quick memory check: what do we call the kind of functions that convert type? And what function specifically could we use here to convert ``'4'`` to an appropriate numerical type? .. hidden-code-block:: python :label: + show/hide response # The functions are called "type conversion" functions. # For this case, the most appropriate function would likely be: int('4') The second part of Line 3 in the help docstring notes that the "trailing newline is stripped" from the string. That means that when we hit Enter, that keypress is not included as a character (such as to start a newline; we will see :ref:`in a later discussion of strings ` how separate lines of text can be specified). Let's try using the function, just with its most basic usage:: input() When we enter the above in any Python environment, the visible cursor will just wait for us to type something and hit Enter. We can try entering in different things. When Python evaluates the input and displays what has been entered, you will notice the quotes wrapped around it, even if the input was just a number---this is just living up to what was described in the help file: *the input function outputs a string of whatever we type.* Our input can be assigned to a variable, such as here:: user_var = input() print("The user input:", user_var) And if we check the type of the variable with ``type(user_var)``, we can verify that it is always a string here, regardless of content. .. container:: qpractice **Q:** What happens if we enter ``5`` in the following input function and code? What value should ``y`` end up with? .. code-block:: x = input() y = 10 + x print(y) .. hidden-code-block:: none :linenos: :label: + show/hide response # We get an Error. The variable x is storing a *string* with # value '5', not an *int* with value of 5. And we cannot add a # string and int. The error message looks like: --------------------------------------------------------------------------- TypeError Traceback (most recent call last) in 1 x = input() ----> 2 y = 10 + x 3 print(y) 4 TypeError: unsupported operand type(s) for +: 'int' and 'str' **Q:** What happens if we input ``5`` in the following? What value should ``y`` end up with now? .. code-block:: x = input() y = 10 * x print(y) .. hidden-code-block:: none :label: + show/hide response # We don't get an error, we get: 5555555555. Or, more specifically, # we get '5555555555' because the type of y here is str (verify!). # We might be surprised by result if we hadn't seen that the * # operator can have a string operand (if the other operand is an # int). As noted in the previous section, it leads to concatenation # of the particular number of strings. Set a prompt ========================================================================== Looking back at the docstring for ``input()``, we notice that there is one optional input we can provide (we look more closely at reading function help files, which have a syntax to get used to, :ref:`here `). The name of the option is "prompt", and we can see by default it has no value, since ``prompt=None``. In computing a **prompt** is something that alerts the user that they should provide input. We discussed prompts in the introductory part of the notes, showing the standard syntax :ref:`for Python environments ` and :ref:`for Linux terminals `. We saw above when using the ``input()`` function that we were just given an empty line to type in, and we had to guess what we were supposed to do; this is because by default no prompt is set (as we have just learned). However, let's try providing a value for the prompt, by providing a string when we use the function (there are different ways to provide inputs to Python functions, which are covered later); see the difference in where we are supposed to type in this case:: input("Input a number:") Note that the prompt does not become part of the input with whatever we type. Also, no extra spaces are put onto the prompt, but if we like, we can add any ourselves for more readability. Let us see how to accept student data from the user using the input function and displaying it using the print function:: name = input("Enter student name: ") country = input("Enter country of origin: ") study = input("Enter field of study: ") print("--- Printing student details ---") print("Student name :", name) print("Country of origin :", country) print("Studying :", study) How does that look when run and evaluated? Convert input type ========================== As noted earlier, the built-in ``input()`` function reads in whatever the user types as a string. Since in real life problems, the user input might be of a different type, you can explicitly convert it to the appropriate type so it can be used by the program. Either of the following could be used to get input and convert the type:: # num1 gets the input string, and num2 is the type-converted version num1 = input("Enter a number") num2 = float(num1) # similar to above, but overwrite the variable itself num3 = input("Enter a number") num3 = float(num3) However, we could also perform type conversion on the input before we even assign it. Consider the logic of the following nested functions:: num4 = float(input("Enter a number")) The ``input()`` function produces a string with the contents of what we type. This in turn becomes the input of the ``float()`` function, and that final evaluation is assigned to a variable. Any of the above do similar tasks. This last one is the most concise. .. container:: qpractice **Q:** Ask for a number from the user, save it and double it. .. hidden-code-block:: none :linenos: :label: + show/hide code num = float(input("Please enter a number: ")) numnum = num * 2 print("Here is your value, doubled:", numnum) It is important to note that Python won't check whether the input is *actually* a number. If the user is prompted for an int but types in ``chicken`` or something, then they will receive an error about trying to convert something non-numerical into an int: .. code-block:: none ValueError: invalid literal for int() with base 10: 'chicken' We will discuss checking the input for good/bad input palues later, using conditionals. *In summary:* * We can use Python to get input from the user---here with the ``input()`` function, and later with reading files. * The input contents will *always* be treated a string initially. If we want to convert it to something else, we can use explicit type conversion to do so. * Receiving and using the input successfully requires knowing *a lot* about what type and format the input should have. Most input readers have specific expectations. * Must of the art of dealing with inputs is deciding on what the input should look like and verifying that it does, to reduce the odds of formatting errors. Practice ============== #. The values output by the ``input()`` function always have what type? #. Write a short code that asks the user for their name and prints "Hello, " followed by the name provided. #. Prompt the user for any input they like and assign their entry to a variable. Evaluate the variable's type and display it. What do you notice, as they enter numbers, words, letters, etc.? #. Get three numbers from the user (e.g., with separate prompts), and display the average. #. A T-shirt costs R150 per unit. Write a short code that asks a customer the number of T-shirts s/he wants to buy and then displays the bill in the form of a table. Your output could look something like: *How many T-shirts do you want?* \.\.\. and if the user were to enter ``10``, then display (using whichever currency you prefer!): .. code-block:: none Price Quantity Total R150 10 R1500 NB: with our current use of ``print()`` and simple spacing of items, it will be hard to have the columns always line up nicely, depending on the number of digits in the Quantity value. This will motivate us to expand our knowledge of combining elements with string formatting, :ref:`which we will do `. #. Write a short code that asks the user for an integer representing a number in seconds, then decomposes it into a number of hours (hrs), minutes (mins) and seconds (secs). Note that the number of minutes should be :math:`< 60`, as should the number of seconds. Your code execution should look something like: *Enter an integer:* \.\.\. and if the user were to enter 8796, then output: .. code-block:: none 8796 seconds = 2 hrs 26 mins 36 secs