python - syntax memo

### python basic
```
# CIN
str = input("enter number") #readIn in String

# COUT
print(str, type(str))  # 29 <class 'str'>


# Convert String to Int
intNum = int(str)
print(intNum, type(intNum))  # 29 <class 'int'>


# String (stored as sequences of letters in memory)
str = 'happy cat'
print(str[0:2]) #ha
print(str[-1]) #t
print(str[::1]) #happy cat
print(str[::-1]) #tac yppah
print(str[0:8:2]) #hpyc

# String Concatination
print('cute' + 'cat') #cutecat
print('cat'*3) #catcatcat

cat1 = 'love'
cat2 = 'sweet'
print(f'My cats are {cat1} and {cat2}') #My cats are love and sweet
print('My cats are {} and {}'.format(cat1, cat2)) 
print('My cats are %s and %s' %(cat1, cat2)) # e.g, %d, %f, %r

```


### List, Dict, Tuple, Set
```
# ------------ LIST ------------ # Mutable sequences
myList = [1, 'a', True]

#append in original List
myList.append(100) #[1, 'a', True, 100]
myList.append(100) #[1, 'a', True, 100]
myList.extend([100, 200]) # [1, 'a', True, 100, 100, 200]
myList.insert(2, '!!!') # [1, 'a', '!!!', True, 100, 100, 100, 200] 
print(myList)

# add element in newly created List
newList = myList + [200] #create new list
print(newList) #[1, 'a', True, 100, 200]

#copy List
originalList = [1, 2, 3, 'a']
copiedList = originalList.copy()
copiedList2 = originalList[:] # [1, 2, 3, 'a']

#sorting
orderingList = [3, 1, 4, 5] 
orderingList.sort() # can not assign into new variable as this will only mutate the original List

newOrderedList = sorted(orderingList) #create NEW List

toBeSortedList = ['bb', 'aa', 'dd']
# print(sorted(toBeSortedList))
sortedBySecond = sorted(toBeSortedList, key = lambda el: el[1])
print(sortedBySecond)

# Get First and Last element of a list
mList = [63, 21, 77, 18, 49, 10]
first, *x, last = mList
print(first) #63
print(last) #10

#Matrix
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for row in range(len(matrix)):
    for col in range(len(matrix[0])):
        print(matrix[row][col])

# Transform Matrix into a List
[matrix[row][col] for row in range(len(matrix)) for col in range(len(matrix[0]))] 
print(matrix)  #[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

# edit element while looping
loopList = [i*2 for i in [1, 2, 3]]#[2, 4, 6]
loopList = [i for i in 'cute cat']
loopList = [i for i in range(0,10) if i % 2 == 0]

# convert String into Char-List
charList = list('myCuteCat')
print(charList, type(charList)) #['m', 'y', 'C', 'u', 't', 'e', 'C', 'a', 't'] <class 'list'>

# sum element in List
sumList = sum([1, 2, 3]) #6

# append to an empty List
empList = []
for i in range(3):
    for j in range(3):
        empList.append(i+j)
print(empList)


# lambda
def func(x):
    func2 = lambda x,y=5: x+y
    return func2(x) + 10
print(func(2)) #17


# Read line of a file into a List
with open("myFile.txt") as f:
    linesToList = [line.strip() for line in f]
print(linesToList)


------------ DICT ------------ # (mapping / hash table)
myDict = {'emotion': 'love', 'energy': 'high'}
myDict['emotion']
listKeys = list(myDict.keys()) # ['emotion', 'energy'] 
listValues =list(myDict.values()) # ['love', 'high']
listAllItems = list(myDict.items()) #[('emotion', 'love'), ('energy', 'high')]

myDict['color'] = 'pink' #{'emotion': 'love', 'energy': 'high', 'color': 'pink'}

tmp = myDict.get('energy') #high

del myDict['energy'] #{'emotion': 'love', 'color': 'pink'}

myDict.pop('emotion') #{'color': 'pink'}

newDict = dict(zip(['name','age','feeling'],['catty',3, False]))
print(newDict) #{'name': 'catty', 'age': 3, 'feeling': False}

extractSpecificItems = {key: value for key, value in newDict.items() if key=='name' or key =='dammy'}
print(extractSpecificItems)  #{'name': 'catty'}

my_dict = {'a':1, 'b':2, 'c':3}
for k,v in my_dict.items():
    print(k)
    print(v)


OrderedDict (preserves the order in which the keys are inserted)
from collections import OrderedDict
od = OrderedDict()
od['a'] = 1




# ------------ SET ------------ # Unordered / Unique (NO Duplicates)
mySet = {1,2,3}
# mySet.remove(100) # Raises KeyError if element not found
# mySet.discard(100) # Doesn't raise an error if element not found

# List to Set
list = [4,5,6]
newSet = set(list)


# Frozen the Set (make it unchangeble)
fSet = frozenset(mySet)
print(fSet)   # frozenset({1, 2, 3})




# ------------ TUPLE ------------ # Immutable() Unable to be changed)/ hashable
# Packs values
myTuple = ('cat', 3, 'kitty')
lastEle = myTuple[-1] #kitty

# UNPACKS values of a variable
(animal, age, type) = myTuple
print(animal) #cat


showIndexOfElement = myTuple.index('kitty')
print(showIndexOfElement) #2

# Zip - Pairing from two different Lists
zl = list(zip([1,2,3],[4,5,6]))
print(zl)  #[(1, 4), (2, 5), (3, 6)]

# Zip - Assign Key-Value
z = [(1, 2), (3, 4), (5, 6), (7, 8)] 
Func = lambda z: list(zip(*z))
Res = Func(z)
print(Res)  # [(1, 3, 5, 7), (2, 4, 6, 8)]


# Tuple Unpacking using *args 
    # In unpacking of tuple number of variables on left-hand side should be equal to number of values in given tuple 
x, *y, z = (2, 'love', 'cute', 'caring', 5)
print(x) #2
print(y) #['love', 'cute', 'caring']
print(z) #5


# ------------ NamedTuple ------------ IMMUTABLE
from collections import namedtuple

Point = namedtuple("Point", "x y")  # Create a namedtuple type, Point

point = Point(1,2) # Instantiate the new type

print(point.x)
print(point[0])

```

### function
```
# ---------- *args -------------------------
def func1(arg1, *argv):
    print('arg1: ', arg1)
    for arg in argv:
        print(arg)
func1('hey', 'thank', 'you', '!!') 

    # output
        # arg1:  hey
        # thank
        # you
        # !!

# -----------**kwargs ---------------------------
def func2(arg1, **kwargs):
    for key,val in kwargs.items():
        print("%s == %s" % (key, val))

func2('hey', first='thank', mid = 'you', last = '!!')

    # output: 
    #     first == thank
    #     mid == you
    #     last == !!


# ------ Other Uses ----------
[*[1,2,3], *[4]]                # [1, 2, 3, 4]
{*[1,2,3], *[4]}                # {1, 2, 3, 4}
(*[1,2,3], *[4])                # (1, 2, 3, 4)
{**{'a': 1, 'b': 2}, **{'c': 3}}# {'a': 1, 'b': 2, 'c': 3}


# ---------- Fibonacci -----------
fib = lambda n : n if n <= 1 else fib(n-1) + fib(n-2) # the last 2 values are the same as their index numbers
result = fib(10)
print(result) #55


# ---------- CLOUSURES -----------
def func1(a):
    def func2(b):
        return a*b
    return func2

firstFunc = func1(2)
secondFunc = firstFunc(5)
print(secondFunc)

# --------------------------------

```

### decorator
```
def decoratorFunc(innerFunc):
    def wrapperFunc():
        print("wrapper starts")

        innerFunc()

        print("wrapper done")
    return wrapperFunc

@decoratorFunc
def detailFunk():
    print('detailFunk')


# driver code
detailFunk()  # same as => decoratorFunc(detailFunk())

```

### logical operartors
```

# 1 < 2 and 4 > 1
# 1 < 2 or 4 > 1

# 1 not in [2,3,4]

# 1 is not 2


# ---------------------------------
myList = [1,3,4,5]
i = len(myList) - 1

while i >= 0:
    val = myList[i]
    if val not in myList:
        break
    else:
        print(val)
        i -= 1
        continue
# ---------------------------------

# ENUMERATE

for i, el in enumerate('cute cat'):
    print(f'{i}, {el}')
```

### map, filter, reduce
```
# ---- map(function, iterables) return after applying the function to each iterable in the sequence----------
tup = (1, 2, 3, 4)
newTuple = tuple(map(lambda x: x + 10, tup))
print(newTuple)


# ---- filter (function, iterables) return true value ----------
y = filter(lambda x: (x < 5), (2, 4, 6, 7)) # y is a filter object
yList = list(y)
print(yList)


# ----- reduce(function, iterables) returns a single value ---------
from functools import reduce
y = reduce(lambda x,y: x+y, [1,2,3,4])
print(y)

```

### CLASS
```
# -----PARENT class
class Instrument:   
    # constructor
    def __init__(self, level):  # c++: Instrument(string str):name(str){};
        self.level = level   
    
    # get value
    def getLevel(self):
        return self.level
    

    # function in a class
    def func(self):
        print('your input: ', self.level)


# ----- Derived class
class Piano(Instrument):  # c++: class Piano:public Instrument{}
    # constructor (1) (inherit duplicate variables and add new one)
    def __init__(self, level, years):
        Instrument.__init__(self, level)
        self.years = years
    
    # construnctor (2)
    def __init__(self, level, years):
        super().__init__(self, level) # c++: Piano():Instrument(){};
        self.years = years



#---- int main(){}-----

# create an object of the class  
obj = Instrument('professional')  # c++: Instrument obj("piano");

# call class-function using the object
obj.func()



# TIPS
# - SELF parameter is a reference to the current instance of the class

```

### sys, argv
```
import sys

if __name__ == '__main__':

    for idx, arg in enumerate(sys.argv):

        print('No. {} == {}'.format(idx, arg))
    
    print('# of arguments passed by commandLine: ', len(sys.argv))

    print('2nd: ', sys.argv[1])   # 2nd:  my



# output: 
# No. 0 == sys_argv.py
# No. 1 == my
# No. 2 == cute
# No. 3 == kitty
# # of arguments passed by commandLine:  4

```

### try, except
```
try:
    f = open("myFile.txt", 'w') # w:create 

    try:
        f.write("cute kitty\n")
    
    # 
    except:
        raise # show error detail on command
        print("failed writing in a file")
    

    

    else:
        print("no error shown while writing in a file") ## executed if no error 
    
    finally:
        f.close()
    
except:
    raise
    print('failed opening a file')

```

### file, csv
```
# ----- READ 
def readFile(name):
    with open(name, encoding='utf-8') as f:
        data = f.readlines()
        for line in data:
            word = line.split()
            print(word)

readFile('myFile.txt')

# ------ WRITE
def writeFile(name, text):
    with open(name, 'a', encoding='utf-8') as f: # w: delete original and write / a: append
        f.write(text)

text = 'text added'
writeFile('myFile.txt', text)



# -------CSV 
import csv
def csvReader


# Dict reader
with open("dictFile.csv", 'r') as f:
    dict_csv = csv.DictReader(f)
    for row in dict_csv:
        print(dict(row))

# Dict writer

with open('players.csv', 'w', newline='') as file:
    fieldnames = ['cat_name', 'age']
    writer = csv.DictWriter(file, fieldnames=fieldnames)

    writer.writeheader()
    writer.writerow({'cat_name': 'love', 'age': 2})
    writer.writerow({'cat_name': 'sweet', 'age': 3})
    writer.writerow({'cat_name': 'honey', 'age': 5})
```

### MODULES
```
# ---- driver.py
def func():
    print('driver __name__ : ', __name__)

if __name__ == '__main__':
    print('driver:name==main')
    func()


# -------- helper.py
import driver

print('helper __name__ : ', __name__)

driver.func()
```