01 Basics of Programming 2
01 Basics of Programming 2
P. Arumugam (आरुमुगम)
Department of Physics
[email protected]
Phone: 8979890366
History of programming languages
High performance computation (HPC)
2
Recent trends
3
https://www.tiobe.com/tiobe-index/
4
More Infographics
Most used programming languages among
developers worldwide as of 2023
0% 10% 20% 30% 40% 50% 60% 70%
JavaScript 63.61%
52.97%
Python 49.28%
48.66%
TypeScript 38.87%
32.37%
Java 30.55%
27.62%
C++ 22.42%
19.34%
PHP 18.58%
13.59%
Go 13.24%
13.05%
Kotlin 9.06%
5
Famous companies that use python
6
Basic architecture
7
A 1-bit computer
8
9
A motherboard
10
Compiler vs Interpreter
11
Data types
12
Naming rules
• You can use any names you want, as long as they follow these rules:
• Names must start with either a letter or an underscore character ( _ ).
• You can't use any of Python's reserved words or keywords.
These are words that have specific meanings to Python, such as if (which
begins an if statement).
• Names are case-sensitive. num is different from NUM and nUm.
• By convention, most Python programmers use lowercase for names that
stand for values. They use other rules for names that stand for functions and
classes
• It's a Good Idea to use meaningful names. If you name everything with a
single-letter, for example, you may have trouble remembering what the name
stands for later.
13
Continuation Lines
14
Simple Text?
15
Unary Operators
16
Arithmetic Operators
17
Relational Operators
18
Logical Operators
19
Bitwise Operators
20
Assignment Operators
21
Membership and Identity Operators
22
Operator precedence
16*2-2/4=?
PEMDAS
• P–
Parentheses.
• E–
Exponentiatio
n.
• M–
Multiplication.
• D b=0
a="y"; – Division.
• A or
a=="y" – Addition.
a=="s" and
b>=2• S –
Subtraction.
Ans: True
23
Associativity of Operators
# Output: 0 # Output: 64
print(5 * (2 // 3)) print((2 ** 3) ** 2)
24
Non associative operators
25
Formatted print
26
Version Meaning
d Signed integer decimal.
i Signed integer decimal.
o Unsigned octal.
u Unsigned decimal.
x Unsigned hexadecimal (lowercase).
X Unsigned hexadecimal (uppercase).
e Floating point exponential format (lowercase).
E Floating point exponential format (uppercase).
f Floating point decimal format.
F Floating point decimal format.
Same as "e" if exponent is greater than -4 or less than precision, "f"
g otherwise.
Same as "E" if exponent is greater than -4 or less than precision, "F"
G otherwise.
c Single character (accepts integer or single character string).
r String (converts any python object using repr()).
s String (converts any python object using str()).
% No argument is converted, results in a "%" character in the result.
27
Formatted print
Flag Meaning
# The value conversion will use the ``alternate form'' (where defined above).
0 The conversion will be zero padded for numeric values.
- The converted value is left adjusted (overrides the "0" conversion if both are given).
+ A sign character ("+" or "-") will precede the conversion (overrides a "space" flag).
28
Formatted print
29
Formatted print
Keywords
and assert break class continue def del elif
else except exec finally for from global if
import in is lambda not
30
Using Escape Sequences
Comments
# This program computes area of rectangle
a=2
b=3
a=b*c # values of b and c are multiplied
# and stored in a
32
Reading input from user
33
Lists & Tuples
SYNTAX:
def function-name(Parameter list):
statements, i.e. the function body
Example:
def fahrenheit(T_in_celsius):
return (T_in_celsius*9/5) + 32
t=float(input(“Enter t: ”))
print(t, ": ", fahrenheit(t))
35
Functions: Optional Parameters
Example:
def Hello(name="everybody"):
print("Hello " + name + "!")
>>> Hello("Peter")
>>> Hello()
Hello Peter!
Hello everybody!
36
Functions: Keyword Parameters
>>> print(sumsub(12,4))
8
>>> print(sumsub(42,15,d=10))
17
>>> print(sumsub(42,15,0,10))
17
>>> print(sumsub())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: sumsub() takes at least 2 arguments (0
given)
37
Functions: Return values
40
Python Scope resolution: LEGB Rule
def fun1():
These rules specific to variable names
x=4
L, Local — Names assigned in any way within a def fun2():
function (def), and not declared global in that print x
bar() # Prints 4
function.
x=5
E, Enclosing function locals — Name in the fun2() # Prints 5
print x # Prints
local scope of any and all enclosing functions
5
(def), from inner to outer.
G, Global (module) — Names assigned at Built-in
the top-level of a module file, or declared Global
global in a def within the file. Enclosing
Local
B, Built-in (Python) — Names
preassigned in the built-in names
module: open, range,...
41
Lists are mutable editable in sub blocks
def f(t):
print(a,b) Changing an element in a mutable
a[1]=5 list defined in enclosing function
# b=b+8
c=[1,2,3] UnboundLocalError: local variable 'b'
return t**2 referenced before assignment
a=[1,2,3]
d=a NameError: name 'c' is not defined
b=2
t=f(5)
#c[1]=9 Referencing the same list !
#print(t,a,b,c) NOT creating a new list !!
print(t,a,b,d) Use d=a.copy() for creating
[1, 2, 3] 2
25 [1, 5, 3] 2 [1, 5, 3] Changing “a” changes “d”
42
Flow control in functions
Sequential Function Nested Function
def fun(x): def fun1(x1):
Start
def fun2(x2):
Start
y2=fun2(x2)
y=fun(x)
Line1
Line2 Start
Line3
def fun(x):
Line4 y1=fun1(x1)
return x**2
Line5
x=int(input("x")
)
y=fun(x)
print(y)
43
Flow control
Yes No
?
Yes ?
No
x=int(input("x") x=int(input("x")
Line1 )
)
Line2
Line3 Yes print(x) No Yes n = 1 No
Line4 while n < x:
if x > 5:
Line5
print("x > 5") print(n)
print("end") n += 1
print("end")
44
if – else statements
Yes No Yes No
? ?
x = int(input("x"))
x=int(input("x")
print(x)
) Yes No
if x > 5:
Yes print(x) No
print("x > 5")
if x > 5:
else:
print("x > 5")
print("x <= 5")
print("end")
print("end")
45
if – elif – else: Nesting
Yes No
? A simple If-else construct
x = int(input("x"))
Yes No print(x)
? Yes
if x > 5: No
47
while loop
# program to calculate the sum of
numbers
# until the user enters zero
total = 0
number = int(input('Enter N: '))
Yes ? while number != 0:
No total += number
number = int(input('Enter next N:
'))
print('total =', total)
x = input("x")
If the condition of a loop is always True, the loop runs
n = 1 for infinite times (until the memory is full).
Yes No
while n < x: age = 32
print(n) # the test condition is always True
while age > 18:
n += 1 print('You can vote')
print("end")
48
while loop with else, break
counter = 0
Yes No
while counter < 3: Inside loop
print('Inside loop') Inside loop
counter = counter + 1 Inside loop
else: Inside else Yes ?
print('Inside else') End No
print('End')
The else block will not execute if the while loop is terminated by a break statement.
counter = 0
Yes while counter < 3: No
if counter == 1: Inside
break loop
End
No
Yes ?
print('Inside loop') ? No
counter = counter + 1 Yes
else:
print('Inside else')
print('End')
49
while loop with continue
No Yes ? No
?
?
No ? Yes
No
Yes
Yes
break continu
e
Continue: skips the current iteration and the control flow goes to the next iteration
num = 0
Yes while num < 10: No
1
num += 1
3
if (num % 2) ==
5
0:
7
continue
9
print(num)
print('End')
50
for loop
A for loop is used to iterate over sequences such as lists, tuples, string, etc.
while: Boolean n=[1,2,3]
for i in 1
expression
n: 2
for: part of sequence? 3
print(i)
Yes ? n=(1,2,3)
1
No for i in
n=[1,2,3] 2
1 n:
for i in n: 3
4 print(i)
print(i)
Yes for i in No n[1]=4 3
1 print(n) [1, 4,
[1,2,3]: 2 3]
print(i) 3
en n=(1,2,3) 1
print("end") d for i in n: 2
print(i) 3
for x in P n[1]=4 TypeError: 'tuple' object does
'PHY': H print(n) not support item assignment
Y
print(x)
51
for loop with break, continue, else
No
for i in [1,2,3,4]: for i in [1,2,3,4]:
if i==3: if i==3:
1 1
break continue
2 2
print(i) print(i)
End 4
else: else:
else
print('else') print('else')
End
print('End') print('End')
for i in range(2): 0
print(i) 1
print('End') End
52
Nested for loops
for i in [1,2,3,4]:
if i==3:
break
for j in i= 1
[1,2,3,4]: j= 1
if j==i: i= 2
break End
print('j= ',j)
print('i= ',i)
print('End') Loops don’t cross and Break exits the inner loop
def fun(n):
for i in for i in [1,2]:
0 1 j=i in: 1 1 1
range(n):
0 2 for i in [1,2]: in: 2 1 2
for j in [1,2]:
1 1 k=i out: 2 1
1 2 2
if i==3: in: 1 2 1
2 1 print('in:',i,j,k)
return 3 in: 2 2 2
2 2 print('out:',i,j,k)
print(i,j) out: 2 2
End
a=fun(5) 2
print('End') print('End') End
53
range command
range(stop)
range(start, stop[, step])
• The arguments to the range constructor must be integers
• Contents of a range r are determined by r[i]=start+step*i where i>=0
• For a positive step r[i]<stop and for a negative step r[i]>stop .
• A range object will be empty if r[0] does not meet the value constraint.
• Ranges do support negative indices, but these are interpreted as indexing from
the end of the sequence determined by the positive indices.
>>> list(range(5, 10)) >>> r = range(0, 20, >>>
[5, 6, 7, 8, 9] 2) r.index(10)
5
>>> list(range(0, 10, 3)) >>> 11 in r
[0, 3, 6, 9] False >>> r[5]
10
>>> list(range(-1, -10, - >>> 10 in r
3)) True >>> r[-1]
[-1, -4, -7] 18
54
More on lists
a = [1,2,3]
print(len(a)) 3
a=[1, "banana",
<class 'list'>
True]
<class 'int'>
print(type(a))
<class 'str'>
for i in a:
<class 'bool'>
print(type(i))
print(a[1]) banana
print(a[-1]) True
print(a[:]) [1, 'banana',
print(a[0:1]) True]
print(a[:1]) [1]
print(a[1:]) [1]
print(a[-3:-1]) ['banana', True]
if "banana" in a: [1, 'banana']
print("success") success
55
More on lists (contd.)
a[1]=5; print(a) [1, 5, True]
a[0:2]=[3,4]; print(a) [3, 4, True]
a[0:1]=[7,8]; print(a) [7, 8, 4, True]
a.insert(1,9); print(a)
[7, 9, 8, 4, True]
a.pop(1); print(a)
[7, 8, 4, True]
a.append('PY’);
[7, 8, 4, True, 'PY']
print(a)
a.append([1,2]);
print(a) [7, 8, 4, True, 'PY', [1, 2]]
a.extend(a); print(a)
a.remove(7); print(a)
[7, 8, 4, True, 'PY', [1, 2], 7, 8, 4, True, 'PY', [1,
2]]
a.sort()
[8, 4, True, 'PY', [1, 2], 7, 8, 4, True,a.count()
'PY', [1,
a.reverse()
a.sort(reverse=Tru
2]] a[::-1] a.index()
e)
i= [n**2 for n in range(1,
Output: [1, 4, 9, 16,
6)]
fruits = ["apple", "banana", "cherry", "kiwi", "mango"]
25]
newlist = [x for x in fruits if "a" in x];
print(newlist)
['apple', 'banana', 'mango']
56
More on lists (contd.)
fruits = ["apple", "banana",
"cherry"]
[green, yellow, red] = fruits apple banana
print(green,yellow,red) cherry
fruits = ["apple", "banana", "cherry", "strawberry"]
[green, yellow, *red] = fruits
apple banana ['cherry',
'strawberry']
Most of these operations (except those which change the values) are applicable for
tuples also. E.g. sort, append, etc., wont work with tuples
Multi-dimensional arrays are
thistuple = ("apple", "banana", "cherry") possible with lists/tuples. We
y = list(thistuple); y.append("orange") will use numpy arrays (to be
thistuple = tuple(y) defined later) for this purpose
>>> a=[[1,2],[3,4]] >>> a[1][0]
>>> a[0] 3
𝑎=
( 1
3
2
4 )
row index
[1, 2] >>> a[0][1]
>>> a[0][0] 2 ( 𝑎11
𝑎21
𝑎12
𝑎22 ) column index
1
57
Lists vs Tuples
# LIST TUPLE
1 Lists are mutable Tuples are immutable
The implication of iterations is Time- The implication of iterations is
2
consuming comparatively Faster
The list is better for performing A Tuple data type is appropriate for
3
operations, such as insertion and deletion. accessing the elements
Tuple consumes less memory as compared
4 Lists consume more memory
to the list
Tuple does not have many built-in
5 Lists have several built-in methods
methods.
Unexpected changes and errors are more
6 In a tuple, it is hard to take place.
likely to occur
58
Sets & Dictionaries
59
match-case
def fundamental_interaction(interaction):
match interaction:
case "Gravitational":
return "Described by Newton's Law of Universal
Gravitation.“
case "Electromagnetic":
return "Described by Maxwell's equations.“
case "Weak Nuclear":
return "Involved in processes like beta decay."
case "Strong Nuclear":
return "Described by Quantum Chromodynamics (QCD)."
case _:
return "Unknown or not a fundamental interaction."
interaction = "Gravitational"
result = fundamental_interaction(interaction)
print(interaction, "Interaction: ", result)
The special pattern _ (and called wildcard) always matches but it doesn’t bind any variables.
60
match-case: def with additional inputs
def calculate_force(interaction_type, quantity1, quantity2, distance):
G = 6.67430e-11 # Gravitational constant in m^3/kg/s^2
k = 8.9875e9 # Coulomb's constant in Nm^2/C^2
match interaction_type:
case "Gravitational":
return (G * quantity1 * quantity2) / (distance ** 2)
case "Electromagnetic":
return (k * abs(quantity1 * quantity2)) / (distance ** 2)
case "Weak Nuclear":
# Custom calculation for weak nuclear force (illustrative)
return quantity1 * quantity2 / distance
case "Strong Nuclear":
# Custom calculation for strong nuclear force (illustrative)
return quantity1 * quantity2 / (distance ** 2)
case _:
return "Unknown interaction type"
interaction = "Gravitational"
quantity1 = 5.972e24
quantity2 = 7.347e22
distance = 384400e3
force = calculate_force(interaction, quantity1, quantity2, distance)
print(interaction, "Interaction Force: ", force, " N")
61
match-case: multiple variables
# point is an (x, y) tuple
match point:
case (0, 0): if x < 0:
print("Origin") raise Exception("only +ve
case (0, y): ")
print(f"Y={y}") if not type(x) is int:
case (x, 0): raise TypeError("Only
print(f"X={x}") integers")
case (x, y):
print(f"X={x}, Y={y}")
case _:
raise ValueError("Not a
point")
-----------------------------------------------
----
ValueError Traceback (most recent call
last)
<ipython-input-4-0e299d68a836> in <module>
5 case _:
----> 6 raise ValueError("Not a point")
7 62
Lambda (inline function)
Python supports the creation of anonymous functions (i.e. functions that are
not bound to a name) at runtime, using a construct called "lambda".
63
Reading Files
file1
• open(filename, mode)
this is line 1
>>> f = open('file1', ‘r')
this is line 2
>>> f=open('file1') this is line 3
>>> f.read()
'this is line 1\nthis is line 2\nthis is line 3\n'
>>> f.read()
''
>>> f.seek(0)
>>> f.read()
'this is line 1\nthis is line 2\nthis is line 3\n'
>>> f.seek(1)
>>> f.read()
'his is line 1\nthis is line 2\nthis is line 3\n'
64
Reading Files
>>> f.close()
65
Various modes for opening files
open(filename, mode)
mode Meaning
'r' open for reading (default)
'w' open for writing, truncating the file first
'x' open for exclusive creation, failing if the file already exists
'a' open for writing, appending to the end of the file if it exists
'b' binary mode
't' text mode (default)
'+' open a disk file for updating (reading and writing)
66
Writing files
• Using the with statement is a good practice because it automatically closes the file
when you're done with it, even if an error occurs within the block.
• Better suited for storing and working with non-textual data, where preserving the binary
structure of the data is essential.
• Text files are designed for human-readable text and may not handle binary data correctly.
68
Writing & reading floating point data
import numpy as np
numbers = np.array([3, np.pi, 1/3, 12345.678534321231321239])
with open('text1.txt', 'w') as tfile1:
tfile1.writelines(("%12.8f \n" % number) for number in
numbers)
with open('text2.txt', 'w') as tfile2:
tfile2.writelines(f"{number}\n" for number in numbers)
with open('bin.npy', 'wb') as bfile:
np.save(bfile, numbers)
with open('text1.txt', 'r') as tfile1:
tn1 = [float(line.strip()) for line in tfile1]
with open('text2.txt', 'r') as tfile2:
tn2 = [float(line.strip()) for line in tfile2]
bn = np.load('bin.npy')
print("Text file1:", tn1-numbers) • Binary files can preserve precision
print("Text file2:", tn2-numbers) and require less storage space.
print("Binary file:", bn-numbers)
Text file1: [ 0.00000000e+00 -3.58979291e-09 -3.33333333e-09 -
1.22963684e-09]
Text file2: [0. 0. 0. 0.]
Binary file: [0. 0. 0. 0.]
69
Some exceptions/options in Python
>>> import numpy as np
>>> a=b=c=1
>>> a=np.arange(3)
>>> a,b,c=1,2,3
>>> a*3
>>> a
array([0, 3, 6])
1
>>> b=[1]
>>> b
>>> b*3
2
[1, 1, 1]
>>> c
>>> np.array(b)*3
3
array([3])
>>> a,b,c=range(1,4)
>>> a
>>> [1]*3
array([0, 1, 2])
[1, 1, 1]
>>> np.dot(a,a)
5
>>> [[0,0],[0,0]]*3
>>> a = [[1, 0], [0,
[[0, 0], [0, 0], [0, 0], [0, 0],
1]]
[0, 0], [0, 0]]
>>> b = [[4, 1], [2,
2]]
>>> np.dot(a, b)
array([[4, 1], 70
Numpy arrays: some notes
>>> a=np.arange(3*2)
>>> np.mat(b)
>>> a.reshape(2,3)
matrix([[0, 1],
array([[0, 1, 2],
[2, 3]])
[3, 4, 5]])
>>> c=np.mat(b)
>>> a=np.arange(4)
>>> c*c
>>> b=a.reshape(2,2)
matrix([[ 2, 3],
>>> b
[ 6, 11]])
array([[0, 1],
[2, 3]])
>>> np.sqrt(c)
>>> b*b
matrix([[ 0. , 1.
array([[0, 1],
],
[4, 9]])
[ 1.41421356,
1.73205081]])
>>> np.dot(b,b)
array([[ 2, 3],
[ 6, 11]])
>>> np.linalg.inv(c)
matrix([[-1.5, 0.5],
[ 1. , 0. ]])
71
Factorials in a loop: global list is efficient
import time 𝑁 2𝑛 start_time = time.time()
𝑛 𝑥
num_terms=8 cos 𝑥=
0
( − 1)∑ ( 2 𝑛) !
cosine_approx1 = 0
flops1 = 0
𝑛=0
x = 0.5 for n in range(num_terms):
def fact1(n): factv,factf=fact1(2*n)
if n == 0: term = ((-1)**n)*(x**(2*n))/factv
return 1, 0 cosine_approx1 += term
result = 1; flops = 0 flops1 += factf+5
for i in range(1,n+1): end_time = time.time()
result *= i time_taken1 = end_time - start_time
flops += 1
return result, flops start_time = time.time()
flops2=fact2(2*num_terms)
def fact2(n): cosine_approx2 = 0
global gfact; gfact=[1] for n in range(num_terms):
flops = 0
for i in range(1, n + 1): term=((-1)**n)*(x**(2*n))/gfact[2*n]
gfact.append(gfact[i- cosine_approx2 += term
1]*i) flops2 += 6
flops += 1 end_time = time.time()
return flops time_taken2 = end_time - start_time
Time, FLOPs & cosine for Approach 1: 0.000998 seconds, 6720, 0.877583
Time, FLOPs & cosine for Approach 2: 0.000000 seconds, 640, 0.877583
http://10.14.0.51/~aru/ph643/fac_cosine.py 72
Numerical Recipes in C: The Art of Scientific
Computing (1986, Cambridge Univ.)
William T. Vetterling, Brian P. Flannery, William
H. Press, Saul Teukolsky
73
Plots with matplotlib.pyplot
import matplotlib.pyplot as plt
plt.plot([1,2,3,4])
plt.show()
To plot x versus y,
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
74
Formatting plots
import numpy as np
import matplotlib.pyplot as plt
75
Working with text
import numpy as np
import matplotlib.pyplot as pl
from matplotlib import rc
rc('text',usetex=True)
x=np.arange(0,11,0.1)
y=x**2
pl.plot(x,y)
pl.xlim(0,10)
pl.title('A Parabola')
pl.xlabel(r'$x$')
pl.ylabel(r'$\psi_n(x)$')
pl.show()
pl.grid(True)
pl.ylabel(r'$\psi_n(x)
$’,fontsize=24,color=‘red’) 76
Working with multiple figures and axes
import numpy as np
import matplotlib.pyplot as plt
def f(t):
return np.exp(-t) * np.cos(2*np.pi*t)
plt.figure(1)
The subplot call specifies
plt.subplot(211) numrows, numcols,
plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')
plot_number where
plot_number ranges from
1 to numrows*numcols.
plt.subplot(212) The commas in the subplot call are
plt.plot(t2, np.cos(2*np.pi*t2), 'r--')optional if numrows*numcols<10.
plt.show() subplot(211) is identical
to subplot(2, 1, 1)
77
Other options in a plot
plt.yscale('linear')
plt.yscale('log')
https://matplotlib.org/stable/tutorials/index.html
78