<jupyter_start><jupyter_text>Table of Contents 1&nbsp;&nbsp;basic types2&nbsp;&nbsp;String operations3&nbsp;&nbsp;Lists3.1&nbsp;&nbsp;Creating lists3.2&nbsp;&nbsp;Subset list elements3.3&nbsp;&nbsp;Reassign list elements3.4&nbsp;&nbsp;Append to list4&nbsp;&nbsp;Tuples5&nbsp;&nbsp;Dictionaries6&nbsp;&nbsp;Looping through containers7&nbsp;&nbsp;Passing by reference8&nbsp;&nbsp;Python ranges9&nbsp;&nbsp;Generators and cartesian products10&nbsp;&nbsp;Functions and arbitrary number of inputs11&nbsp;&nbsp;Classes and Objects12&nbsp;&nbsp;Class inheritance Before continuting with pandas, let's look at Python as a programming language itself.Hopefully it'll give you insight into how and why things are the way they are  basic types<jupyter_code>3
type(3)
int(3.14)
float(3)
'strings'
True
False
"string"<jupyter_output><empty_output><jupyter_text>String operations<jupyter_code>'string'
"it's here"
# adding strings will concatenate them
"hello" + "world"
# 2 strings next to eachother also concatenates
"hello""world"<jupyter_output><empty_output><jupyter_text>Lists  Creating lists<jupyter_code># lists can store any arbitrary object
my_list = ['a', 1, True, 3.14]
my_list<jupyter_output><empty_output><jupyter_text>Subset list elements<jupyter_code>my_list[0]
my_list[0:3]<jupyter_output><empty_output><jupyter_text>Reassign list elements<jupyter_code>my_list[0] = 'zzzz'
my_list<jupyter_output><empty_output><jupyter_text>Append to list<jupyter_code># append a string to the end
my_list.append('new appended value')
my_list
# append a list to the end
my_list.append(['a1', 'a2'])
my_list
my_list[5]
my_list[5][1]
my_list
# pop returns the last element and remove it from the list
my_list.pop()
my_list
# insert into a specific index in a list
my_list.insert(0, 'insert0')
my_list
# copy a list
my_list.copy()
my_list2 = my_list.copy()<jupyter_output><empty_output><jupyter_text>Tuples<jupyter_code>my_tuple = ('a', 1, True, 3.14)
my_tuple
type(my_tuple)
my_tuple[0]
my_tuple[0] = 'zzzz'<jupyter_output><empty_output><jupyter_text>Dictionaries<jupyter_code>my_dict = {'fname': 'Daniel'}

my_dict
my_dict = {'name': ['Daniel', 'Chen']}
my_dict = 3
my_dict
isinstance('this is a string', str)
my_dict = {'name': ['Daniel', 'Chen'],
          'languages': ['Python', "R"]}
my_dict
my_dict['languages']
my_dict['noExist']
my_dict.get('languages')
my_dict.get('noExist')
print(my_dict.get('noExist'))
None
my_dict.keys()
my_dict.values()
my_dict.items()
new_item = {'new_item_1': 'new_item'}
new_item
my_dict.update(new_item)
my_dict
new_replace = {
    'languages': ['English', 'really bad chinese'],
    'new_item_2': 'new_item'
}
my_dict.update(new_replace)
my_dict
new_item_t = {
    (3, 4): ['s1', 's2']
}
my_dict.update(new_item_t)
my_dict
my_dict[(3, 4)]
my_dict['languages'] = 'asdf'
my_dict<jupyter_output><empty_output><jupyter_text>Looping through containers<jupyter_code>my_list = ['a', 1, True, 3.14]
my_list
for item in my_list:
    print('in list')
    print(item)
    
print('out of loop')
idx = 0
for item in my_list:
    print(my_list[idx])
    # idx = idx + 1
    idx += 1
# enumerate returns the index and the value in the list
for idx, item in enumerate(my_list):
    print(idx)
    print(item)
    print('*'*80)
# to itherate through a dictionary you can iteratate through the `items`
for k, v in my_dict.items():
    print(k)
    print(v)<jupyter_output>name
['Daniel', 'Chen']
languages
asdf
new_item_1
new_item
new_item_2
new_item
(3, 4)
['s1', 's2']<jupyter_text>Passing by reference<jupyter_code># the below series of code should be something you should remember
# when you think you are subsetting and 'saving' a slice of your list
# when you actually end up working directly on the list
# this is when you would use 'copy'
l = [1, 2, 3, [4, 5, 6]]
b = l[3]
l
b
b[0] = 'asdf'
b
l
# copy
# deepcopy
l = [1, 2, 3]
# ipython timeit magic
%%timeit
l2 = []
for i in l:
    l2.append(i * i)
l2
%%timeit
lc = [i*i for i in l]
lc<jupyter_output><empty_output><jupyter_text>Python ranges<jupyter_code>for i in [12, 3, 4]:
    print(i)
for i in range(10):
    print(i)
range(10)
list(range(10))<jupyter_output><empty_output><jupyter_text>Generators and cartesian products<jupyter_code>import itertools
prod = itertools.product([1, 2, 3], ['a', 'b', 'c'], [10, 20, 30])
prod
for idx, i in enumerate(prod):
    print(idx)
    print(i)
    values = list(i)
    print(values)
# we still have our product iterator,
# however since we've already exhausted the generator,
# if you run the above code again
# without re-creating the generator
# it will return nothing
prod
for idx, i in enumerate(prod):
    print(idx)
    print(i)
    values = list(i)
    print(values)<jupyter_output><empty_output><jupyter_text>Functions and arbitrary number of inputs<jupyter_code>def my_mean(x, y):
    return (x + y) / 2
my_mean(10, 20)
def my_mean(*args):
    total = 0
    count = 0
    for i in args:
        total += i
        count += 1
    return total / count
my_mean(10, 15, 20)
my_mean(10, 20)
my_mean(0, 100)
def my_mean(x, *args):
    total = 0
    count = 0
    for i in args:
        total += i
        count += 1
    return total / count
my_mean(10, 15, 20)
def my_mean(x, y=0, *args, **kwargs):
    total = 0
    count = 0
    for i in args:
        total += i
        count += 1
    return total / count<jupyter_output><empty_output><jupyter_text>Classes and Objects<jupyter_code>class Person(object):
    def __init__(self, fname, lname, age):
        """this is the constructor
        """
        self.first_name = fname
        self.last_name = lname
        self.age = age
    def birthday(self):
        self.age += 1
        print('happy birthday')
    
    def sum(x, y):
        return x + y
        
p1 = Person('daniel', 'chen', 28)
p1
p1.first_name
p1.age
p1.birthday()
p1.age
Person.sum(3, 4)
p1.yo = 3
p1.yo<jupyter_output><empty_output><jupyter_text>Class inheritance Watch this for inheritance!Super in python does not do what Super does in other languages!https://www.youtube.com/watch?v=EiOglTERPEo<jupyter_code>class Daniel(Person):
    def __init__(self):
        super(Daniel, self).__init__('Daniel', 'Chen', 28)
d = Daniel()
d
d.first_name<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12987431517885917, 'fraction_numerical': 0.025781501772478246, 'mean_word_length': 4.8501413760603205, 'pattern_counts': {'":': 0, '<': 60, '<?xml version=': 0, '>': 60, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '15', 'dir': 'jupyter-structured-clean-dedup', 'id': '227200', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 2431, 'n_tokens_neox': 2309, 'n_words': 615, 'path': 'class/09-python_intro.ipynb', 'repo_name': 'chendaniely/2017-10-26-mckinsey', 'size': '6206'}