2. Variables & Types#
Kristaps Stolarovs and Afiq Bin Nor Kamil
kristaps.stolarovs@manchester.ac.uk
Department of Mechanical and Aerospace Engineering, The University of Manchester, Manchester, UK
2.1. Intended Learning Outcomes#
After reading this page, you should be able to:
Describe the basic definition and properties of variables and types.
Declare simple variables.
Identify the different variable types available in Python.
Specify the data type of a variable.
Determine the data type of any variable.
2.2. What are Variables?#
Variables are containers in which data values are stored. You are already aware of the existance of variables, and use them constantly. For example, observe this algebraic equation:
In this case, \(a\), \(b\) and \(c\) are variables used to represent unknown values. The distinction made in programming is that a variable can represent any data type, whether it be an integer, character, a complex number, paragraph, matrix, etc.
When a value is assigned to a variable, Python reserves a memory location to store them. Calling up a specific variable by its reference (name) later in the program enables Python to retrieve the assigned value.
2.2.1. Example:#
x = 2
y = 4
z = "Python is easy!"
print(x + y)
print(z)
6
Python is easy!
As you can see, variables in Python are declared just as they are in MATLAB.
2.3. Variable scopes#
The variable scope refers to the regin of a program in which a variable can be accessed and referenced from. In Python, variables can have 3 types of scope:
Local
Global
Nonlocal
2.3.1. Local variables#
A local variable is created when a namespace (such as a function) is invoked, and destroyed when the function is terminated. For more information about functions, refer to the Functions chapter.
Local variables cannot be accessed outside of their scope. They are used to isolate data within a function, preventing accidental modifications and naming clashes from other parts of the code. As a consequence, local variables with the same name assignment in different functions or nested functions will not interfere with one another.
2.3.1.1. Example:#
# Define a function
def function1():
pi = 3.14159
print(pi)
# Define another function
def function2():
pi = "The circumference of a circle divided by its diameter."
print(pi)
# Call the function. Notice that the value of pi is different in each function.
function1()
function2()
3.14159
The circumference of a circle divided by its diameter.
# Try to print pi outside the function
print(pi)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[3], line 2
1 # Try to print pi outside the function
----> 2 print(pi)
NameError: name 'pi' is not defined
As you can see, when we tried to print our variable pi out by invoking the function, we had the expected output. However, when pi was called outside of the function, Python returned a NameError, telling us that pi has not been defined.
2.3.2. Global variables#
To acces pi outside of the function, we can declare it outside of the function. We can also declare a global variable inside a function by using the keyword global before defining the variable. Global variables allow for data sharing across multiple functions or blocks without the need to pass them as arguments. They can be used to cache data or store results that are to be reused in different parts of the program.
Please note that it is generally considered good practice to avoid global variables when they are not necessary.
2.3.2.1. Example:#
# Define a global variable
pi = 3.14159
# Define a function
def function3():
print(pi)
# Call the function
function3()
3.14159
# Try to print pi outside the function
print(pi)
3.14159
2.3.2.2. Example:#
# Define a function
def function4():
global euler # Declare that euler is a global variable
euler = 2.71828
print(euler)
# Call the function
function4()
2.71828
# Try to print euler outside the function
print(euler)
2.71828
2.3.3. Nonlocal variables#
Nonlocal variables are used in nested functions to reference variables from the outer (enclosing) function. Unlike global variables which can be accessed throughout the entire program, nonlocal variables are only accessible within their enclosing function’s scope. The nonlocal keyword is used to indicate that a variable belongs to the enclosing (outer) function rather than the local scope. Without using the nonlocal keyword, any assignment to x in the inner function would create a new local variable instead of modifying the outer function’s variable. This is different from global variables because nonlocal variables can only access the nearest enclosing scope, not the global scope. For more information, refer to the Functions chapter.
2.3.3.1. Example (with nonlocal):#
# Define an outer function
def outer_function():
x = "outer value"
# Define a nested function
def inner_function():
nonlocal x # Declare that x is from the outer function
x = "modified value"
print("Inside inner function:", x)
print("Before inner function:", x)
inner_function()
print("After inner function:", x)
# Call the outer function
outer_function()
Before inner function: outer value
Inside inner function: modified value
After inner function: modified value
2.3.3.2. Example (without nonlocal):#
# Define an outer function
def outer_function():
x = "outer value"
# Define a nested function
def inner_function():
x = "modified value" # Creates a new local variable
print("Inside inner function:", x)
print("Before inner function:", x)
inner_function()
print("After inner function:", x) # Original value remains unchanged
# Call the outer function
outer_function()
Before inner function: outer value
Inside inner function: modified value
After inner function: outer value
2.4. Naming convention#
When writing code, it is recommended that you not only use comments (in Python these start with #), but that your code itself is self-descriptive and easy to read. One way to achieve this is to use variable names which are descriptive enough to describe the purpose of a variable without being too long. There are a number of requirements and recommendations when naming variables. The recommendations are derived from the “PEP 8” Python style guide. For example:
A variable must only contain letters, numbers and/or the underscore (
_) symbol (required by Python).
example_variable_1 = 5
print(example_variable_1)
5
The following naming is not allowed:
example_variable_1! = 5
print(example_variable_1!)
File "/tmp/ipykernel_41047/741251450.py", line 1
example_variable_1! = 5
^
SyntaxError: invalid syntax
A variable can only start with a letter or underscore (required by Python).
_example_variable_2 = 6
print(_example_variable_2)
6
1_example_variable_3 = 7
print(1_example_variable_3)
File "/tmp/ipykernel_41047/353339031.py", line 1
1_example_variable_3 = 7
^
SyntaxError: invalid token
Variable names are case-sensitive (a feature of Python).
manchester = "University of Manchester"
print(Manchester)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
/tmp/ipykernel_41047/2150243049.py in <module>
1 manchester = "University of Manchester"
----> 2 print(Manchester)
NameError: name 'Manchester' is not defined
print(manchester)
University of Manchester
Variables should not have the same name as keywords reserved by Python (required by Python).
and = 9
print(and)
File "/tmp/ipykernel_41047/3685409330.py", line 1
and = 9
^
SyntaxError: invalid syntax
The variable name is descriptive, yet still reasonably short (recommended, not necessary).
e = 2.71828 # Too short
euler = 2.71828 # Good
the_euler_constant = 2.71828 # Too long
Your code uses a single naming concention throughout (recommended, not necessary). There are 3 common naming conventions, camelCase, snake_case and PascalCase. Please note, you should avoid using PascalCase in Python, as Python conventionally uses capital letters for class names and constants, while lowercase letters are for variable names.
manUni = "University of Manchester" # Camel case
man_uni = "University of Manchester" # Snake case
ManUni = "University of Manchester" # Pascal case (not recommended)
2.5. Variable declaration#
When we introduce a variable (such as when we write pi = 3.14159), we declare the variable. In Python, this is done by writing the variable name, and equals sign, and then the intended value of the variable.
Python allows for multiple variables to be assigned the same value, as well as assigning different values to specific variables in a single line. Variables can be declared anywhere within the program, depending on the intended scope for the variables to be accessible. They can also be declared without a value by using the None keyword. It is important to note that Python uses dynamic typing (more on this later).
2.5.1. Example:#
colour = "blue"
print(colour)
blue
colour = shirt = "blue"
print(colour, shirt)
blue blue
colour, shirt = "blue", "polo"
print(colour, shirt)
blue polo
empty_variable = None
print(empty_variable)
None
2.6. Variable assignment & manipulation#
In Python, variables are created and assigned values in a single step. Technically, a variable is simply a reference to an object stored in memory - like a label that points to where the actual data is stored. A variable can be reassigned to different values at any time. While the objects that variables refer to may be immutable (like strings or numbers) or mutable (like lists) (more on this later), the variables themselves can always be reassigned.
colour = "blue"
print(colour)
colour = "red"
print(colour)
blue
red
Variables can be used in operations such as mathematical calculations or string manipulation. Variables can also be deleted using the del statement, however this is generally not necessary in Python, as it has a robust and well-optimized “garbage collector” that automatically manages memory by collecting and deleting objects that are no longer referenced by any variables.
2.7. What are data types?#
In programming, data types are a very important concept.
A data type is a classification or category that specifies the type of value a variable can hold. As mentioned earlier, python is dynamically typed, meaning that variables do not have a fixed data type. This in theory makes coding easier, but it is a false comfort, as dynamic typing introduces many pitfalls which you must be very careful of (we will briefly cover this later). Here are the fundamental Python data types you’ll use most often:
Numeric Types:
int(integers): Whole numbers like 5, -17, 1000float(floating-point): Decimal numbers like 3.14, -0.001, 2.0complex: Complex numbers like 3+4j (Python uses j for the imaginary unit)
Text Type:
str(string): Text data like “Hello”, ‘Python’ (you can use either double- or single-quotes)
Boolean Type:
bool: Logical values True or False. In Python, these are implemented as integers (1 for True, 0 for False), which is a very useful quirk.
Collection Types:
list: Ordered, mutable sequences, written as [1, 2, 3]tuple: Ordered, immutable sequences like (1, 2, 3)dict(dictionary): Key-value pairs like {“name”: “John”, “age”: 30}set: Unordered collections of unique elements like {1, “apple”, 3, True}
2.7.1. Numeric types#
Numerical data types (int, float, complex) store numbers. They are immutable, meaning once a number object is created, that specific object cannot be modified. When you perform operations on numbers, Python creates new number objects rather than modifying existing ones.
2.7.1.1. Example:#
a = 5 # a is an integer
print(a)
b = 2.5 # b is a float
print(b)
c = 2 + 3j # c is a complex number
print(c)
5
2.5
(2+3j)
2.7.1.2. Example:#
x = 5 # Creates a number object with value 5
y = x # y now references the same number object
x = x + 1 # This doesn't modify the original 5, it creates a new number 6
# Now x references the new 6 object, while y still references 5
print (x, y)
6 5
2.7.2. Text type#
Strings (str) store sequences of characters (text). Just like numeric types, they are immutable. Strings can be created using single quotes ' or double quotes ".
text = "Hello"
print(text)
Hello
text2 = text + " World!"
print(text2)
Hello World!
text3 = 'Python is easy!'
print(text3)
Python is easy!
2.7.3. Boolean type#
Booleans (bool) represent logical values:
TrueFalse
In Python, any object can be evaluated as a Boolean using the bool() function. In this case, most empty values evaluate to False, while non-empty or non-zero values evaluate to True.
is_valid = True
has_error = False
# Examples of boolean evaluation
bool("") # False (empty string)
bool(0) # False
bool(42) # True
bool([]) # False (empty list)
False
2.7.4. Collection types#
Collection types include sequences (lists, tuples), which are fully covered in the Lists, tuples, and dictionaries chapter, as well as mappings and sets. These types exceed the scope of this chapter, so they will not be covered here.
2.8. Conversion & checking#
Python provides built-in functions to convert data from one type to another. This process is called type conversion or casting. There are two types of conversion:
2.8.1. Type checking#
Python provides several ways to check the type of a variable:
type(): Returns the type of an objectisinstance(): Checks if an object is an instance of a specific type
x = 5
print(type(x)) # <class 'int'>
print(isinstance(x, int)) # True
print(isinstance(x, (int, float))) # True (checks multiple types)
print(isinstance(x, float)) # False
<class 'int'>
True
True
False
2.8.2. Implicit conversion (Coercion)#
Sometimes, Python automatically converts one data type to another without any user intervention. This happens when:
Mixing numeric types in operations (integers are converted to float)
Using numeric types in boolean contexts
2.8.2.1. Example:#
x = 5 # integer
print(x)
y = 2.5 # float
print(y)
z = x + y # z will be a float (7.0)
print(z)
if x: # 5 is converted to True
print("x is truthy")
w = 0 # integer
if w: # 0 is converted to False
print("w is truthy")
else:
print("w is falsy")
5
2.5
7.5
x is truthy
w is falsy
2.8.3. Explicit conversion (Casting)#
When we deliberately convert one data type to another using conversion functions, we refer to it as explicit conversion or casting. Common conversion functions include:
int(): Converts to integerfloat(): Converts to floatstr(): Converts to stringbool(): Converts to booleanlist(): Converts to listtuple(): Converts to tupleset(): Converts to set
2.8.3.1. Example:#
# String to number conversion
x = "5" # x = "5" (string)
print("x is a", type(x))
x = int(x) # x = 5 (integer)
print("after casting, x is a", type(x))
y = "2.5" # y = "2.5" (string)
print("y is a", type(y))
y = float(y) # y = 2.5 (float)
print("after casting, y is a", type(y))
x is a <class 'str'>
after casting, x is a <class 'int'>
y is a <class 'str'>
after casting, y is a <class 'float'>
# Number to string conversion
z = 123 # z = 123 (integer)
print("z is a", type(z))
z = str(z) # z = "123" (string)
print("after casting, z is a", type(z))
z is a <class 'int'>
after casting, z is a <class 'str'>
# Number to number conversion
a = 5 # a = 5 (integer)
print("a is a", type(a), "with value", a)
a = float(a) # a = 5.0 (float)
print("after casting, a is a", type(a), "with value", a)
b = 2.5 # b = 2.5 (float)
print("b is a", type(b), "with value", b)
b = int(b) # b = 2 (integer)
print("after casting, b is a", type(b), "with value", b)
a is a <class 'int'> with value 5
after casting, a is a <class 'float'> with value 5.0
b is a <class 'float'> with value 2.5
after casting, b is a <class 'int'> with value 2
Notice that the decimal part is truncated, not rounded.
# Other common conversions
my_string = "Python"
print("my_string is a", type(my_string), "and has value", my_string)
my_list = list(my_string)
print("my_list is a", type(my_list), "and has value", my_list)
my_tuple = tuple(my_list)
print("my_tuple is a", type(my_tuple), "and has value", my_tuple)
my_set = set(my_tuple)
print("my_set is a", type(my_set), "and has value", my_set)
my_string is a <class 'str'> and has value Python
my_list is a <class 'list'> and has value ['P', 'y', 't', 'h', 'o', 'n']
my_tuple is a <class 'tuple'> and has value ('P', 'y', 't', 'h', 'o', 'n')
my_set is a <class 'set'> and has value {'n', 'o', 'P', 'h', 't', 'y'}
Notice that the order of the elements in the set is different from the original string. This is because sets are unordered collections, so the order of the elements is not guaranteed.
2.8.4. Common pitfalls#
Not all conversions are possible, and some might not work as expected.
While this works:
# This works
x = int("123")
type(x)
int
This will raise errors:
# These raise errors
y = int("hello") # ValueError: invalid literal for int()
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
/tmp/ipykernel_41047/2827831990.py in <module>
1 # These raise errors
----> 2 y = int("hello") # ValueError: invalid literal for int()
ValueError: invalid literal for int() with base 10: 'hello'
z = int("3.14") # ValueError: invalid literal for int()
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
/tmp/ipykernel_41047/4141682078.py in <module>
----> 1 z = int("3.14") # ValueError: invalid literal for int()
ValueError: invalid literal for int() with base 10: '3.14'
Like mentioned before, casting a float to int will truncate the value, not round.
2.9. The Perils of Dynamic Typing#
While Python’s dynamic typing provides flexibility, it can lead to subtle and difficult-to-debug issues, especially if you are not familiar with Pythons coercion.
For example, in C++ (a statically typed language), a variable’s type must be defined when it is declared:
int main() {
int x = 5
}
Whereas in Python, we do not have to specify a type:
x = 5
The consequence of this is that you do not control the type that python selects for you, which can lead to sometimes confusing and unpredictable bugs. Here are some examples.
2.9.1. Erroneous type coecrion#
Python’s automatic type coercion can sometimes produce unexpected results:
# String concatenation vs numeric addition
x = "5"
y = 2
print(x + str(y)) # "52" (string concatenation)
print(int(x) + y) # 7 (numeric addition)
print(x * y) # "55" (string repetition)
print(x + y) # TypeError: can only concatenate str (not "int") to str
52
7
55
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_41047/3219089787.py in <module>
5 print(int(x) + y) # 7 (numeric addition)
6 print(x * y) # "55" (string repetition)
----> 7 print(x + y) # TypeError: can only concatenate str (not "int") to str
TypeError: can only concatenate str (not "int") to str
This is especially dangerous in loops or with user input:
numbers = ["1", 2, "3", 4]
total = 0
for num in numbers:
total += num # TypeError on second iteration
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_41047/2062962047.py in <module>
2 total = 0
3 for num in numbers:
----> 4 total += num # TypeError on second iteration
TypeError: unsupported operand type(s) for +=: 'int' and 'str'
2.9.2. Silent type changes#
Functions might return different types based on inputs or conditions, which can cause errors far from the original source:
def divide(a, b):
return a / b
result1 = divide(10, 2) # Returns 5.0 (float)
result2 = divide(10, 5) # Returns 2.0 (float)
result3 = divide(1, 0) # Raises ZeroDivisionError
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
/tmp/ipykernel_41047/1964470385.py in <module>
4 result1 = divide(10, 2) # Returns 5.0 (float)
5 result2 = divide(10, 5) # Returns 2.0 (float)
----> 6 result3 = divide(1, 0) # Raises ZeroDivisionError
/tmp/ipykernel_41047/1964470385.py in divide(a, b)
1 def divide(a, b):
----> 2 return a / b
3
4 result1 = divide(10, 2) # Returns 5.0 (float)
5 result2 = divide(10, 5) # Returns 2.0 (float)
ZeroDivisionError: division by zero
# This might break later in unexpected ways
def process_numbers(numbers):
return [x + 1 for x in numbers] # Assumes all numbers are numeric
data = [divide(10, 2), divide(15, 5), "3"] # Mixed types!
process_numbers(data) # TypeError on the string "3"
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/tmp/ipykernel_41047/975506437.py in <module>
1 data = [divide(10, 2), divide(15, 5), "3"] # Mixed types!
----> 2 process_numbers(data) # TypeError on the string "3"
/tmp/ipykernel_41047/4289532198.py in process_numbers(numbers)
1 # This might break later in unexpected ways
2 def process_numbers(numbers):
----> 3 return [x + 1 for x in numbers] # Assumes all numbers are numeric
/tmp/ipykernel_41047/4289532198.py in <listcomp>(.0)
1 # This might break later in unexpected ways
2 def process_numbers(numbers):
----> 3 return [x + 1 for x in numbers] # Assumes all numbers are numeric
TypeError: can only concatenate str (not "int") to str
2.9.4. Mutable default arguments#
One of Python’s most infamous errors:
def add_to_list(item, my_list=[]): # An innocent empty list, which in theory should be created anew each time.
my_list.append(item)
return my_list
print(add_to_list(1)) # [1]
print(add_to_list(2)) # [1, 2] - Surprise! The list persisted!
print(add_to_list(3)) # [1, 2, 3] - The default list is shared between calls
[1]
[1, 2]
[1, 2, 3]
This happens because default arguments are evaluated when the function is defined, not when it’s called. The default value is created only once and is attached to the function object. All subsequent calls to the function with no second argument will use the same list object, and because lists are mutable, it will simply keep appending to the same list.
2.10. Precision#
Python’s handling of numbers, particularly floating-point numbers, can sometimes lead to surprising results due to how numbers are represented in binary. Understanding these limitations is crucial for accurate calculations.
2.10.1. Floating point precision#
Floating-point numbers in Python (and most programming languages) use IEEE-754 double-precision format, which can lead to unexpected results:
# Simple arithmetic that doesn't work as expected
print(0.1 + 0.2) # Returns 0.30000000000000004
print(0.1 + 0.2 == 0.3) # Returns False! This is especially problematic in comparisons.
# More examples of precision issues
print(0.3 + 0.3 + 0.3) # 0.8999999999999999
print(0.1 * 3) # 0.30000000000000004
0.30000000000000004
False
0.8999999999999999
0.30000000000000004
This is because the double-precision format consists of a floating point stored using 64 bits (1s and 0s), in binary. The range of representable real numbers is between \(10^{-308}\) and \(10^{308}. Additionally, there is an upper bound to the relative approximation error due to rounding in floating point number systems. This is referred to as the machine epsilon value. A simple explanation is to think of it as the difference between 1.0 and the least value greater than 1.0 that is representable as a float. For Python's ```float``` data type, this is generally \)2^{-52}$.
2.10.2. Integer precision#
Integers in Python 3 have unlimited precision (they can be as large as your computer’s memory allows):
# Very large numbers work fine
print(2 ** 100) # 1267650600228229401496703205376
# But mixing with floats can lead to precision loss
print(2 ** 100 + 0.1) # Precision of decimals is lost
# An extremely large number
print(2 ** 10000) # No problem
# If you mix floats with extremely large numbers, you may even run into OverflowError
print(2 ** 10000 + 0.1) # OverflowError: int too large to convert to float
1267650600228229401496703205376
1.2676506002282294e+30
19950631168807583848837421626835850838234968318861924548520089498529438830221946631919961684036194597899331129423209124271556491349413781117593785932096323957855730046793794526765246551266059895520550086918193311542508608460618104685509074866089624888090489894838009253941633257850621568309473902556912388065225096643874441046759871626985453222868538161694315775629640762836880760732228535091641476183956381458969463899410840960536267821064621427333394036525565649530603142680234969400335934316651459297773279665775606172582031407994198179607378245683762280037302885487251900834464581454650557929601414833921615734588139257095379769119277800826957735674444123062018757836325502728323789270710373802866393031428133241401624195671690574061419654342324638801248856147305207431992259611796250130992860241708340807605932320161268492288496255841312844061536738951487114256315111089745514203313820202931640957596464756010405845841566072044962867016515061920631004186422275908670900574606417856951911456055068251250406007519842261898059237118054444788072906395242548339221982707404473162376760846613033778706039803413197133493654622700563169937455508241780972810983291314403571877524768509857276937926433221599399876886660808368837838027643282775172273657572744784112294389733810861607423253291974813120197604178281965697475898164531258434135959862784130128185406283476649088690521047580882615823961985770122407044330583075869039319604603404973156583208672105913300903752823415539745394397715257455290510212310947321610753474825740775273986348298498340756937955646638621874569499279016572103701364433135817214311791398222983845847334440270964182851005072927748364550578634501100852987812389473928699540834346158807043959118985815145779177143619698728131459483783202081474982171858011389071228250905826817436220577475921417653715687725614904582904992461028630081535583308130101987675856234343538955409175623400844887526162643568648833519463720377293240094456246923254350400678027273837755376406726898636241037491410966718557050759098100246789880178271925953381282421954028302759408448955014676668389697996886241636313376393903373455801407636741877711055384225739499110186468219696581651485130494222369947714763069155468217682876200362777257723781365331611196811280792669481887201298643660768551639860534602297871557517947385246369446923087894265948217008051120322365496288169035739121368338393591756418733850510970271613915439590991598154654417336311656936031122249937969999226781732358023111862644575299135758175008199839236284615249881088960232244362173771618086357015468484058622329792853875623486556440536962622018963571028812361567512543338303270029097668650568557157505516727518899194129711337690149916181315171544007728650573189557450920330185304847113818315407324053319038462084036421763703911550639789000742853672196280903477974533320468368795868580237952218629120080742819551317948157624448298518461509704888027274721574688131594750409732115080498190455803416826949787141316063210686391511681774304792596709376
---------------------------------------------------------------------------
OverflowError Traceback (most recent call last)
/tmp/ipykernel_41047/2310060744.py in <module>
9
10 # If you mix floats with extremely large numbers, you may even run into OverflowError
---> 11 print(2 ** 10000 + 0.1) # OverflowError: int too large to convert to float
OverflowError: int too large to convert to float
2.10.3. Dealing with precision issues#
Several approaches exist to handle precision issues:
Using the decimal module
from decimal import Decimal, getcontext
# Set precision level (number of decimal places)
getcontext().prec = 4
# More precise decimal calculations
print(Decimal('0.1') + Decimal('0.2')) # Exactly 0.3
print(Decimal('1') / Decimal('7')) # 0.1429
0.3
0.1429
Using round()
# Round to specific decimal places
print(round(0.1 + 0.2, 1)) # 0.3
print(round(2.675, 2)) # 2.67 (Note: be careful with rounding!)
0.3
2.67
Using math.isclose()
from math import isclose
# Compare floating point numbers safely
print(isclose(0.1 + 0.2, 0.3)) # True
print(isclose(0.1 + 0.2, 0.3, rel_tol=1e-9)) # Specify relative tolerance
True
True
Generally, using round() will most likely be sufficient, however it is important to be aware of these potential issues.
2.11. Summary#
Variables are used to represent and store data, which can be split into local and global variables.
Various operations can be done on variables to manipulate and update their values such as declaration, assignment, manipulation and deletion.
Data types refer to the classification or category that specifies the type of value a variable can hold.
There are many data types in Python which allows for compatible data conversion to be done to achieve a set of tasks.
Floating point numbers have unique limitations which can lead to precision and accuracy issues.
For more information, visit the online Python documentation - https://docs.python.org/3/
2.12. Exercise#
Exercise: You are building a weather monitoring system, and would like to monitor certain parameters. Using Python variables, perform the following tasks:
Create a variable storing today’s temperature in Celsius (you can use 4.2)
Convert this temperature to Fahrenheit using the formula: \((\text{Celsius} * 9/5) + 32\)
Store the temperature in Kelvin as well (\(\text{Kelvin} = \text{Celsius} + 273.15\))
Create a boolean variable that indicates if it’s above freezing (above 0°C)
Hint: use an
ifstatement,if celsius > 0:If you are stuck, refer to the chapter Conditional statements
Store the temperature unit “Celsius” as a string
Create a variable that combines a number and a string to show “24.5 Celsius” (using the original Celsius value)
Print out all values with appropriate labels using the
print()statement.
The output might look like:
Temperature in Celsius: 18.3
Temperature in Fahrenheit: 214.3
Temperature in Kelvin: 999.65
Above freezing? False
Temperature reading: 24.5 Celsius
2.12.1. Solution#
celsius = 40.5
fahrenheit = celsius * 9/5 + 32
kelvin = celsius + 273.15
if celsius > 0:
above_freezing = True
else:
above_freezing = False
celsius_str = str(celsius)
temperature = str(celsius) + " Celsius"
print("Temperature in Celsius:", celsius)
print("Temperature in Fahrenheit:", fahrenheit)
print("Temperature in Kelvin:", kelvin)
print("Above freezing?", above_freezing)
print("Temperature reading:", temperature)
Temperature in Celsius: 40.5
Temperature in Fahrenheit: 104.9
Temperature in Kelvin: 313.65
Above freezing? True
Temperature reading: 40.5 Celsius