# 2 Built-in Data Types

## 2.1 Numbers

Two types of built-in number type, integer and float.

### 2.1.1 Integer

n = 123
type (n)
#:> <class 'int'>

### 2.1.2 Float

f = 123.4
type (f)
#:> <class 'float'>

### 2.1.3 Number Operators

In general, when the operation potentially return float, the result is float type. Otherwise it return integer.

Division always return float

print(4/2)  # return float
#:> 2.0
type(4/2)
#:> <class 'float'>

Integer Division by integer return inter. Integer division by float return float.

print (8//3,'\n',    # return int
8//3.2)       # return float
#:> 2
#:>  2.0

Remainder by integer return integer.
Remainder by float return float

print (8%3, '\n',    # return int
8%3.2)        # return float
#:> 2
#:>  1.5999999999999996

Power return int or float

print (2**3)    # return int
#:> 8
print (2.1**3)  # return float
#:> 9.261000000000001
print (2**3.1)  # return float
#:> 8.574187700290345

## 2.2 String

String is an object class ‘str.’ It is an ordered collection of letters, an array of object type str

import string
s = 'abcde'
print( '\nvar type  = ', type(s),
'\nelems     = ',s[0], s[1], s[2],
'\nlen       = ', len(s),
'\nelem type = ',type(s[1]))
#:>
#:> var type  =  <class 'str'>
#:> elems     =  a b c
#:> len       =  5
#:> elem type =  <class 'str'>

### 2.2.1 Constructor

#### 2.2.1.1 Classical Method

class str(object='')

my_string = str()        ## empty string

class str(object=b'', encoding='utf-8', errors='strict')

my_string = str('abc')

#### 2.2.1.2 Shortcut Method

my_string = 'abc'

#### 2.2.1.3 Multiline Method

my_string = '''
This is me.
Yong Keh Soon
'''
print(my_string)
#:>
#:> This is me.
#:> Yong Keh Soon

Note that the variable contain \n front and end of the string.

my_string
#:> '\nThis is me.\nYong Keh Soon\n'

#### 2.2.1.4 Immutability

• String is immuatable. Changing its content will result in error
s = 'abcde'
print ('s : ', id(s))
#s[1] = 'z'               # immutable, result in error
#:> s :  139903753637552
• Changing the variable completley change the reference (for new object)
s = 'efgh'
print ('s : ', id(s))
#:> s :  139903753596272

### 2.2.2 Class Constants

#### 2.2.2.1 Letters

print( 'letters = ', string.ascii_letters,
'\nlowercase = ',string.ascii_lowercase,
'\nuppercase = ',string.ascii_uppercase )
#:> letters =  abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
#:> lowercase =  abcdefghijklmnopqrstuvwxyz
#:> uppercase =  ABCDEFGHIJKLMNOPQRSTUVWXYZ

#### 2.2.2.2 Digits

string.digits
#:> '0123456789'

#### 2.2.2.3 White Spaces

string.whitespace
#:> ' \t\n\r\x0b\x0c'

### 2.2.3 Instance Methods

#### 2.2.3.1 Substitution : format()

By Positional

print( '{} + {} = {}'.format('a', 'b', 'c'),         # auto sequence
'\n{0} + {1} = {2}'.format('aa', 'bb', 'cc')) # manual sequence
#:> a + b = c
#:> aa + bb = cc

By Name

'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W') ## constant
#:> 'Coordinates: 37.24N, -115.81W'

By Dictionary Name

coord = {'latitude': '37.24N', 'longitude': '-115.81W'} ## dictionary key/value
'Coordinates: {latitude}, {longitude}'.format(**coord)
#:> 'Coordinates: 37.24N, -115.81W'

Formatting Number

Float

'{:+f}; {:+f}'.format(3.14, -3.14)  # show it always
#:> '+3.140000; -3.140000'
'{: f}; {: f}'.format(3.14, -3.14)  # show a space for positive numbers
#:> ' 3.140000; -3.140000'
'Correct answers: {:.2f}'.format(55676.345345)
#:> 'Correct answers: 55676.35'

Integer, Percentage

'{0:,}   {0:.2%}   {0:,.2%}'.format(1234567890.4455)
#:> '1,234,567,890.4455   123456789044.55%   123,456,789,044.55%'

Alignment

'{0:<20}   {0:<<20}'.format('left aligned')
#:> 'left aligned           left aligned<<<<<<<<'
'{0:>20}  {0:>20}'.format('right aligned') #:> ' right aligned right aligned'
'{:^30}'.format('centered')  # use '*' as a fill char
#:> '           centered           '

#### 2.2.3.2 Substitution : f-string

my_name = 'Yong Keh Soon'
salary  = 11123.346
f'Hello, {my_name}, your salary is {salary:,.2f} !'
#:> 'Hello, Yong Keh Soon, your salary is 11,123.35 !'

#### 2.2.3.3 Conversion: upper() lower()

'myEXEel.xls'.upper()
#:> 'MYEXEEL.XLS'
'myEXEel.xls'.lower()
#:> 'myexeel.xls'

#### 2.2.3.4find() pattern position

string.find() return position of first occurance. -1 if not found
s='I love karaoke, I know you love it oo'
print (s.find('lov'))
#:> 2
print (s.find('kemuning'))
#:> -1

#### 2.2.3.5strip() off blank spaces

filename = '  myexce l.   xls   '
filename.strip()
#:> 'myexce l.   xls'

#### 2.2.3.8 Replacement: .replace()

string = "geeks for geeks geeks geeks geeks"

# Prints the string by replacing geeks by Geeks
print(string.replace("geeks", "Geeks"))

# Prints the string by replacing only 3 occurrence of Geeks   
#:> Geeks for Geeks Geeks Geeks Geeks
print(string.replace("geeks", "GeeksforGeeks", 3)) 
#:> GeeksforGeeks for GeeksforGeeks GeeksforGeeks geeks geeks

### 2.2.4 Operator

#### 2.2.4.1% Old Style Substitution

https://docs.python.org/3/library/stdtypes.html#old-string-formatting

my_name = 'Yong Keh Soon'
salary  = 11123.346
'Hello, %s, your salary is %.2f !' %(my_name, salary)
#:> 'Hello, Yong Keh Soon, your salary is 11123.35 !'

#### 2.2.4.2+ Concatenation

'this is ' + 'awesome'
#:> 'this is awesome'

#### 2.2.4.3in matching

For single string, partial match

print( 'abc' in '123abcdefg' )
#:> True

For list of strings, exact match (even though only one element in list).
For partial match, workaround is to convert list to single string

print( 'abc' in ['abcdefg'],             # false
'abc' in ['abcdefg','123'],       # fakse
'abc' in ['123','abc','def'],     # true
'abc' in str(['123','abcdefg']))  # true
#:> False False True True

#### 2.2.4.4 Comparitor

a='abc'
b='abc'
print('id(a) = ', id(a),
'\nid(b) = ', id(b),
'\na == b  ', a==b)
#:> id(a) =  139904199793840
#:> id(b) =  139904199793840
#:> a == b   True

### 2.2.5 Iterations

string[start:end:step]  # default start:0, end:last, step:1

If step is negative (reverse), end value must be lower than start value

s = 'abcdefghijk'
print (s[0])       # first later
#:> a
print (s[:3])      # first 3 letters
#:> abc
print (s[2:8 :2])  # stepping
#:> ceg
print (s[-1])      # last letter
#:> k
print (s[-3:])     # last three letters
#:> ijk
print (s[:   :-1]) # reverse everything
#:> kjihgfedcba
print (s[8:2 :-1])
#:> ihgfed
print (s[8:2])     # return NOTHING

## 2.3 Boolean

b = False

if (b):
print ('It is true')
else:
print ('It is fake')
#:> It is fake

### 2.3.1 What is Considered False ?

Everything below are false, anything else are true

print ( bool(0),      # zero
bool(None),  # none
bool(''),    # empty string
bool([]),    # empty list
bool(()),    # empty tupple
bool(False), # False
bool(2-2))    # expression that return any value above
#:> False False False False False False False

### 2.3.2and operator

BEWARE !

• and can return different data types
• If evaluated result is True, the last True Value is returned (because python need to evaluate up to the last value)
• If evaluated result is False, the first False Value will be returned (because python return it immediately when detecting False value)
print (123 and 2 and 1,
123 and [] and 2)
#:> 1 []

### 2.3.3not operator

not (True)
#:> False
not (True or False)
#:> False
not (False)
#:> True
not (True and False)
#:> True
~(False)
#:> -1

### 2.3.4or operator

• or can return different data type
• If evaluated result is True, first True Value will be returned (right hand side value need not be evaluated)
• If evaluated result is False, last Fasle Value will be returned (need to evalute all items before concluding False)
print (1 or 2)
#:> 1
print (0 or 1 or 1)
#:> 1
print (0 or () or [])
#:> []

## 2.4 None

### 2.4.1 None is an Object

• None is a Python object NonType
• Any operation to None object will result in error
• For array data with None elements, verification is required to check through iteration to determine if the item is not None. It is very computaionaly heavy
type(None)
#:> <class 'NoneType'>
t1 = np.array([1, 2, 3, 4, 5])
t2= np.array([1, 2, 3, None, 4, 5])
print( t1.dtype  , '\n\n',    # it's an object
t2.dtype)
#:> int64
#:>
#:>  object

### 2.4.2 Comparing None

Not Prefered Method

null_variable = None
print( null_variable == None )
#:> True

Prefered

print( null_variable is None )
#:> True
print( null_variable is not None )
#:> False

### 2.4.3 Operation on None

Any operator (except is) on None results in error.

None & None
#:> Error in py_call_impl(callable, dots$args, dots$keywords): TypeError: unsupported operand type(s) for &: 'NoneType' and 'NoneType'
#:>
#:> Detailed traceback:
#:>   File "<string>", line 1, in <module>