Operators#

Statements, Expressions, and Functions#

  • Any Python program/script consists of a series of statements and expressions

  • Statements

    • Code that tells the Python interpreter to do something and does not (typically) generate an output

    • E.g., import statement to load additional functions and classes

    • E.g., del statement to remove objects and modules from the current scope

    • Other Python statements:

      • break, pass, continue, … - simple statements

      • if, while, for, with, def, class, … - compound statements

  • Expressions

    • Code that combines objects, function calls and operators

    • Evaluates to a value

    • Examples:

      • 2 + 2

      • 2 + 3 5.2/7.5

      • 3.1*sin(2.1𝜋), …

    • Expressions will display in the console when evaluated

2 + 4 # An expression
6
a = 2 + 4 # A statement
del a # Another statement
  • Functions

    • Reusable code that outlines a procedure to do something using statements, expressions and other functions

    • Can be called multiple times and be part of expressions

The print function#

  • Built in function used to display specified messages and contents of specified objects

  • Syntax: print(object(s), sep=' ', end='\n', file=sys.stdout, flush=False)

    • To be discussed in more detail in a later module

x = 10
y = 20
z = 40
print("x = ", x, "\ny = ", y, "\nz = ", z)
x =  10 
y =  20 
z =  40

The help  function#

  • Built in function that displays documentation of functions, modules, etc.

  • Syntax: help(object) where object is the object you want information about

help(4.5)
Help on float object:

class float(object)
 |  float(x=0, /)
 |  
 |  Convert a string or number to a floating point number, if possible.
 |  
 |  Methods defined here:
 |  
 |  __abs__(self, /)
 |      abs(self)
 |  
 |  __add__(self, value, /)
 |      Return self+value.
 |  
 |  __bool__(self, /)
 |      True if self else False
 |  
 |  __ceil__(self, /)
 |      Return the ceiling as an Integral.
 |  
 |  __divmod__(self, value, /)
 |      Return divmod(self, value).
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __float__(self, /)
 |      float(self)
 |  
 |  __floor__(self, /)
 |      Return the floor as an Integral.
 |  
 |  __floordiv__(self, value, /)
 |      Return self//value.
 |  
 |  __format__(self, format_spec, /)
 |      Formats the float according to format_spec.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getnewargs__(self, /)
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __hash__(self, /)
 |      Return hash(self).
 |  
 |  __int__(self, /)
 |      int(self)
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __mod__(self, value, /)
 |      Return self%value.
 |  
 |  __mul__(self, value, /)
 |      Return self*value.
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __neg__(self, /)
 |      -self
 |  
 |  __pos__(self, /)
 |      +self
 |  
 |  __pow__(self, value, mod=None, /)
 |      Return pow(self, value, mod).
 |  
 |  __radd__(self, value, /)
 |      Return value+self.
 |  
 |  __rdivmod__(self, value, /)
 |      Return divmod(value, self).
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __rfloordiv__(self, value, /)
 |      Return value//self.
 |  
 |  __rmod__(self, value, /)
 |      Return value%self.
 |  
 |  __rmul__(self, value, /)
 |      Return value*self.
 |  
 |  __round__(self, ndigits=None, /)
 |      Return the Integral closest to x, rounding half toward even.
 |      
 |      When an argument is passed, work like built-in round(x, ndigits).
 |  
 |  __rpow__(self, value, mod=None, /)
 |      Return pow(value, self, mod).
 |  
 |  __rsub__(self, value, /)
 |      Return value-self.
 |  
 |  __rtruediv__(self, value, /)
 |      Return value/self.
 |  
 |  __sub__(self, value, /)
 |      Return self-value.
 |  
 |  __truediv__(self, value, /)
 |      Return self/value.
 |  
 |  __trunc__(self, /)
 |      Return the Integral closest to x between 0 and x.
 |  
 |  as_integer_ratio(self, /)
 |      Return integer ratio.
 |      
 |      Return a pair of integers, whose ratio is exactly equal to the original float
 |      and with a positive denominator.
 |      
 |      Raise OverflowError on infinities and a ValueError on NaNs.
 |      
 |      >>> (10.0).as_integer_ratio()
 |      (10, 1)
 |      >>> (0.0).as_integer_ratio()
 |      (0, 1)
 |      >>> (-.25).as_integer_ratio()
 |      (-1, 4)
 |  
 |  conjugate(self, /)
 |      Return self, the complex conjugate of any float.
 |  
 |  hex(self, /)
 |      Return a hexadecimal representation of a floating-point number.
 |      
 |      >>> (-0.1).hex()
 |      '-0x1.999999999999ap-4'
 |      >>> 3.14159.hex()
 |      '0x1.921f9f01b866ep+1'
 |  
 |  is_integer(self, /)
 |      Return True if the float is an integer.
 |  
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |  
 |  __getformat__(typestr, /)
 |      You probably don't want to use this function.
 |      
 |        typestr
 |          Must be 'double' or 'float'.
 |      
 |      It exists mainly to be used in Python's test suite.
 |      
 |      This function returns whichever of 'unknown', 'IEEE, big-endian' or 'IEEE,
 |      little-endian' best describes the format of floating point numbers used by the
 |      C type named by typestr.
 |  
 |  fromhex(string, /)
 |      Create a floating-point number from a hexadecimal string.
 |      
 |      >>> float.fromhex('0x1.ffffp10')
 |      2047.984375
 |      >>> float.fromhex('-0x1p-1074')
 |      -5e-324
 |  
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |  
 |  __new__(*args, **kwargs)
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  imag
 |      the imaginary part of a complex number
 |  
 |  real
 |      the real part of a complex number

Python Operators#

  • Operators in python - special symbols that operate on various Python data types

  • Assignment operators

    • Used to initialize variables with values or objects

    • In Python, assignment is a statement while all other operators result in an expression

  • Arithmetic operators

    • For arithmetic operation on built-in data types (int, float, etc.)

    • Can be extended to custom data types, i.e., user defined classes (e.g., vectors, matrices, quaternions)

  • Comparison or relational operators

    • For comparing objects (e.g., numbers and strings)

  • Logical operators

    • For performing Boolean logic (working with True and False values)

  • Bitwise operators

    • Operations on individual bits that the value of an object stores

  • Membership and identity test operators

Assignment Operator#

Assignment (=)

  • In Python, this is a statement which means it does not generate any output

  • Used to assign or reassign (i.e., overwrite) values to an identifier

  • Assignment can be normal, simultaneous, or cascaded

    • Normal assignment is preferred

# Normal assignment - preferred
x = 2
y = 3 + 5
print(x, y, sep='     ')
2     8
# Simultaneous assignment
x, y = 2, 3 + 5
print(x, y, sep='\n')
2
8
# Cascaded assignment
x = y = z = 2
print(x, y, z, sep='\n')
2
2
2
  • Assignment operator in programming is not the same as mathematical equality

a = 10
b = a
print("a = ", a, "\nb = ", b)
a =  10 
b =  10
a = 20
print("a = ", a, "\nb = ", b)
a =  20 
b =  10

Arithmetic Operators in Python#

Mathematical Operators

  • Addition +

  • Subtraction –

  • Multiplication *

  • Division /

  • Floor (Integer) Division //

  • Modulus %

  • Exponentiation **

  • Addition (+)

    • Addition of int, float, bool, and complex data types is allowed

      • Boolean values True and False evaluate to 1 and 0, respectively

    • The output data type of addition depends on the input data types

      • E.g., if the addition involves a complex number, the sum will be of complex type

      • The int value when added to a float or complex type should be within the float limits (±1.79e+308)

    • Addition of two strings is allowed - concatenation

a = 1 + True # int + bool
b = 1.2 + 2j + True # complex + bool
s1, s2 = 'Go ', 'Cougs!'
print(a, b, s1 + s2, sep='\n')
2
(2.2+2j)
Go Cougs!
  • Subtraction (-)

    • Same as addition except cannot be used with strings

'Hello ' - 'World!'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[12], line 1
----> 1 'Hello ' - 'World!'

TypeError: unsupported operand type(s) for -: 'str' and 'str'
  • Multiplication (*)

    • Numeric types and Boolean types can be multiplied

    • The resulting type, like addition, depends on the inputs

      • The int value when multipled with a float or complex type should again be within the float limits

    • A string can be multiplied by a bool or int type

a = 1*False        # int * bool
b = (2.4+5j)*3.2   # complex * float

print(a, type(a), '', b, type(b), sep='\n')
0
<class 'int'>

(7.68+16j)
<class 'complex'>
'Hello, '*3 # Equivalent to concatening the string 3 times
'Hello, Hello, Hello, '
a = 'I exist'*True
b = 'I exist'*False
print(a, b, sep='\n')
I exist
  • Division (/)

    • String division is not permitted

    • If a complex type is involved, the result will be complex

    • Otherwise, the result will be of the float type

x = 6 + 1j
y = 2
z = x/y
print(z)
type(z)
(3+0.5j)
complex
a = 4/2
print(a, type(a), sep='\n')
2.0
<class 'float'>
  • Division by zero (or False) results in a ZeroDivisionError error or exception from the interpreter

4/False
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Cell In[225], line 1
----> 1 4/False

ZeroDivisionError: division by zero
  • Floor (Interger) Division (//)

    • Gives the quotient or the integer part of a division operation

    • The result is always an integer but not necessarily of integer type

    • When the dividend is very close to an integer, Python essentially rounds it

a = 10 // 5
b = 12 // 5
c = 9.9999_9999_9999_999 // 5
d = 9.9999_9999_9999_9999 // 5

print(a, b, c, d, sep='\t')
2	2	1.0	2.0
  • Remainder or modulo (%)

    • Gives the remainder of a division operation

a = 10 % 5
b = 12 % 5
c = 9.9999_9999_9999_999 % 5
d = 9.9999_9999_9999_9999 % 5

print(a, b, c, d, sep='\t')
0	2	4.999999999999998	0.0
  • Operators // and % do not work with the complex type

  • The quotient and remainder can be simultaneously calculated using the divmod function

    • divmod(x, y) = (x // y, x % y)

divmod(12.2, 7.1)
(1.0, 5.1)
height = 66      # Units: inches
IN_PER_FT = 12   # Inches per feet
#feet = height//IN_PER_FT
#inch = height%IN_PER_FT
feet, inch = divmod(height, IN_PER_FT)

print(str(height) + " inches is " + str(feet) + " feet and " + str(inch) + " inches")
66 inches is 5 feet and 6 inches
  • Exponentiation (**)

    • Can be applied to Boolean and numeric types

    • Resulting type depends on the operands

a = 2**200          # Exact value of type int
b = 2.**200         # Approximate value of type float
c = 2.**(200 + 0j)  # Approximate value of type complex

print(a, type(a), b, type(b), c, type(c), sep='\n')
1606938044258990275541962092341162602522202993782792835301376
<class 'int'>
1.6069380442589903e+60
<class 'float'>
(1.6069380442589903e+60+0j)
<class 'complex'>

Augmented Assignment Operators#

  • Shorthand operators for assignment following an arithmetic operation (+, -, *, /, //, %, **)

    • 𝑥 = 𝑥⟨𝑜𝑝⟩𝑦 is equivalent to 𝑥 ⟨𝑜𝑝⟩= 𝑦

    • ⟨𝑜𝑝⟩ can be any of the arithmetic operators

#x = 3
x += 1   # Same as x = x + 1
print(x)
40
x *= 3 # Same as x = x * 3
x
39

Warning: Programs are meant to be executed sequentially. However with the cell-based interactive nature of notebooks, code can be executed in an arbitrary manner. Be aware of this fact.

Comparison Operators#

  • Comparison operators compare the values of two objects

  • The result of comparison is of Boolean type (True or False)

  • Python provides the following comparison operators

    • Equals to (==)

    • Not equal to (!= or <>)

    • Greater than (>) and greater than or equal to (>=)

    • Less than (<) and less than or equal to (<=)

  • Comparison operators <, <=, >, >= cannot be used with the complex data type

x, y = 5, 10
x != y
True
2.e+500 == 2.e+503 # Special behavior
True
  • Both LHS and RHS evaluate to the special float value inf and are considered equal

  • Any attempt to compare nan with anything (even with itself) will evaluate to False

Logical Operators#

  • Operate on Boolean type variables and expressions that evaluate to the Boolean type

  • Three logical operators in Python – and, or, not

  • The result is also of type bool and is determined by the truth tables for each logical operator

P

Q

P and Q

P or Q

not P

True

True

True

True

False

True

False

False

True

False

False

True

False

True

True

False

False

False

False

True

x,y,z = 5, 10, 20
P = x < y
Q = y > z
P and 
False
a, b, c, d = 10, 10, 20, 10
(a <= b) and (b < c) and (c > d)
True
a <= b < c > d  # Same as above
True
  • Logical operators work on non-Boolean data types or expressions too

  • x and y (assume x and y are two arbitrary Python expressions)

    • The expression x is evaluated first

    • If x is False, x and y evaluates to x and y is not evaluated

    • Otherwise, x and y evaluates to y

  • x or y

    • The expression x is evaluated first

    • If x is True, x or y evaluates to x and y is not evaluated

    • Otherwise, x or y evaluates to y

0.1 and 2.4/0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Cell In[319], line 1
----> 1 0.1 and 2.4/0

ZeroDivisionError: float division by zero
"  " or 3*2
'  '
  • A value of 0 in any number type evaluates to False

  • An empty string also evaluates to False

Operator Precedence#

  • Python arithmetic operators follow PEMDAS

    • Parentheses – expressions within () are evaluated with the highest precedence

    • Exponentiation (**)

    • Positive, negative, bitwise NOT (+x, -x, ~x)

    • Multiplication, division, floor division, remainder (*, /, //, %)

    • Addition and subtraction (+, -)

    • Shifts <<, >>

    • Bitwise operators AND, XOR and OR, in that order

    • Comparison, membership and identity test operators

    • Boolean operators not, and and or, in that order

  • Operators with the same precedence are evaluated left to right except exponentiation which is evaluated right to left

  • When in doubt, just make liberal use of parentheses

2 + 3 * 4
14
  • * takes precedence over + and is evaluated first

(2 + 3) * 4
20
  • If additiion operation is to be evaluated first, use parentheses ()

2 * 3 // 4
1
  • * and // have the same precedence, so operations are evaluated left to right

2**2**3
256
  • Both ** operations have the same precedence, they are evaluated right to left

  • Use parentheses () if the first exponentiation is to be evaluated first

(2**2)**3
64