<jupyter_start><jupyter_text>OOP shortcuts* Built-in functions that take care of common tasks in one call (so useful)* File I/O and context managers* An alternative to method overloading* Functions as objects *len, reverse, enumerate*..., *all, any*..., *eval, exec, compile* (I don't use these...)*hasattr, getattr, setattr, and delattr*, which allow attributes on anobject to be manipulated by their string names.*zip*, which takes two or more sequences and returns a new sequence of tuples, where each tuple contains a single value from each sequence.And many more! See the interpreter help documentation for each of the functions listed in dir(\__builtins__).<jupyter_code>a_list = [1,2,3,4,5]
print('len() builtin: {}'.format(len(a_list)))
print('__len__ attr: {}'.format(a_list.__len__()))
print()
print('look at reversed')
print('a_list: {}'.format(a_list))
print('reversed(a_list): {}'.format(reversed(a_list)))
print('the reversed list: {}'.format(list(reversed(a_list))))
print()

for item in reversed(a_list):
    print(item)
a_string_list = ['one', 'two', 'three', 'four', 'five']
for i,item in enumerate(a_string_list):
    print('item {}: {}'.format(i, item))

print()
for i,item in zip(a_list, a_string_list):
    print('item {}: {}'.format(i, item))

print('mismatched lengths: takes first n-elements of second item in zip')
for i,item in zip(a_list[1:3], a_string_list):
    print('item {}: {}'.format(i, item))
dir(__builtins__)
dir(sum)<jupyter_output><empty_output><jupyter_text>File I/O and context managers* writing* reading* context managers<jupyter_code>contents = "Some file contents\n"
file = open("filename.txt", "w")
file.write(contents)
file.close()

file = open("filename2.txt", "w")
file.writelines([contents]*3)
file.close()

# this overwrites every time... also explicit management of open and close
# binary add wb, rb

dir(file)<jupyter_output><empty_output><jupyter_text>context managers* with open(...) as file... calls __enter__ and __exit__ methods on the file object* cleans up need for 'startup' and 'cleanup' code<jupyter_code>with open("filename.txt", "w") as file:
    file.write(contents)
    
with open("filename_seq_cm.txt", "w") as file:
    file.writelines([contents]*3)
with open("./a-text-file.txt", "r") as file:
    for i,  line in enumerate(file.readlines()):
        print("line {}: {}".format(i+1, line))
# custom string joiner
class StringJoiner(list):
    def __enter__(self):
        return self
    
    def __exit__(self, type, value, tb):
        self.result = "".join(self)

import random, string

with StringJoiner() as joiner:
    for i in range(15):
        joiner.append(random.choice(string.ascii_letters))

print(joiner.result)

# but...
same_thing = ''.join([random.choice(string.ascii_letters) for i in range(15)])
print(same_thing)<jupyter_output>VjMLIieQzDfnaDl
QkxyOnpvtLqjdFA<jupyter_text>An alternative to method overloading* Python doesn't permit multiple methods with the same name!!* instead, write the function with expectation of argument type<jupyter_code>def func1(arg1):
    print('original func1')
    pass

def func1(arg2):
    print('the function has been replaced')
    pass

func1('some arg')
Python functions accept:
* positional arguments
* keyword arguments (with default values)
def function(pos1, pos2, kwd1='None', kwd2=5):
    print('pos1: {}'.format(pos1))
    print('pos2: {}'.format(pos2))
    print('kwd1: {}'.format(kwd1))
    print('kwd2: {}'.format(kwd2))
    pass

#function(1)
#function(1,2)
#function(1, 2, kwd1='2')
#function(2,['hi'], kwd1={'some':'key-value'}, kwd2=('a', 'tuple'))

# specify all inputs out of order
function(pos2=2, pos1=['hi'], kwd2={'some':'key-value'}, kwd1=('a', 'tuple'))
# variable argument lists
def extract_list(*somelist):
    
    print(somelist)
    for item in somelist:
        print(item)

extract_list()
#extract_list(1)
#extract_list(tuple(range(10))) # feel free to fiddle with this one
#extract_list(1,2,3,4)
#extract_list('item1', 'item2', 'item3')
class Options:
    default_options = {
        'port': 21,
        'host': 'localhost',
        'username': None,
        'password': <PASSWORD>,
        'debug': False
    }
    
    def __init__(self, **kwargs):
        self.options = dict(Options.default_options) # set the default options
        self.options.update(kwargs) # update based on user input, can also add keys for the options
        
    def __getitem__(self, key):
        return self.options[key]
    
    
# sample1 = Options(username='dusty', password='<PASSWORD>', some_other_option=True)
# print(sample1.options)

sample2 = Options()
print(sample2.options)
sample2['port']<jupyter_output>{'port': 21, 'host': 'localhost', 'username': None, 'password': <PASSWORD>, 'debug': False}<jupyter_text>Ordering of arguments:* positional* \*list argument* keyword arguments* \** dictionary to hold anything else<jupyter_code>import shutil
import os.path
def augmented_move(target_folder, *filenames, verbose=False, **specific):
    '''Move all filenames into the target_folder, allowing specific treatment of certain files.'''
    
#     # print args
    print('target_folder: {}'.format(target_folder))
    print('filenames: {}'.format(filenames))
    print('verbose: {}'.format(verbose))
    print('specific: {}'.format(specific))
    
    def print_verbose(message, filename):
        '''print the  message only if verbose is enabled'''
        
        if verbose:
            print(message.format(filename))
    
    ## augmented_move block
    # to get the example to work...
    filenames = list(filenames)          # comes in as a tuple
    filenames.extend(specific.keys())    # use list.extend
    
    for filename in filenames:
        target_path = os.path.join(target_folder, filename)
        if filename in specific:
            if specific[filename] == 'ignore':
                print_verbose("Ignoring {}", filename)
                
            elif specific[filename] == 'copy':
                print_verbose("Copying {}", filename)
                shutil.copyfile(filename, target_path)

        else:

            try:
                print_verbose("Moving {}...", filename)
                shutil.move(filename, target_path)
            except:
                print('file {} does not exist'.format(filename))
                
augmented_move("target_folder", "one", verbose=True, two="ignore", three="ignore")<jupyter_output>target_folder: target_folder
filenames: ('one',)
verbose: True
specific: {'two': 'ignore', 'three': 'ignore'}
Moving one...
file one does not exist
Ignoring two
Ignoring three<jupyter_text>Unpacking arguments* can provide arguments as sequence, list, or dictionary<jupyter_code>def show_args(arg1, arg2, arg3="THREE"):
    print(arg1, arg2, arg3)
    
some_args = range(2)
more_args = {
    "arg1": "ONE",
    "arg2": "TWO"
}


show_args(*some_args)
show_args(**more_args)
# a more practical example for us...
from shapely.geometry import box
bounds = [0,0,5,10]
box(*bounds)
# help(box)<jupyter_output><empty_output><jupyter_text>Treating functions like objects* if you want, you can set descriptions or any other named attribute on a function    * why would you want to do this?* you have access to the \__name__ attributeLet's go through the timer example because I found it odd...<jupyter_code>def function_object():
    '''help doc'''
    pass

function_object.whatever = 'something'
function_object.whatever, function_object.__name__
# help(function_object)<jupyter_output><empty_output><jupyter_text>PyTorch DataLoader example - Sampling an image -- won't work if you don't have the data/libraries... so don't worry about it!! I've kept it for the figures.<jupyter_code>from test_unet_helpers import get_points_list, gtDatasetSampler2

gt_image_2 = '../smart_cities/rasters/union_impervious_raster_2_0_0_wgs84.tif'
dg_id = '1030010057062200'
shpfile = '../smart_cities/union/union.shp'

coords = get_points_list(gt_image_2, dg_id, shpfile, num=100)
coords
from torch.utils.data import Dataset
import rasterio 
import numpy as np
import torch

class gtDatasetSampler2(Dataset):
    """DG Dataset"""
    def __init__(self, gtfile, coord_pair, window_size=64, transform=None):
        """ 
        Args:
            image_dir(string): the folder containing the DG images
            transform (callable, optional): Optional transform to  be applies
        """
        self.image_file = gtfile
        self.transform = transform
        self.coords = coord_pair
        self.window_size = window_size
        
    
    def __getitem__(self, idx):
        
        with rasterio.open(self.image_file, 'r') as src:
            temp = src.read()
        
        # get the window
        r,c = self.coords[idx]
        r_start = int(r - self.window_size/2)
        r_end = int(r_start + self.window_size)
        c_start = int(c - self.window_size/2)
        c_end = int(c_start + self.window_size)
        
        # extract the window
        img_arr = temp[0,r_start:r_end, c_start:c_end]
        img_arr = np.expand_dims(img_arr, axis=0)

        # set no data to 0
        img_arr[img_arr == 3] = 0
        
        # convert to tensor
        img_arr = torch.from_numpy(img_arr).float()
        
        return img_arr
    
    def __len__(self):
        return len(self.coords)

from torchvision.transforms import ToTensor, Normalize, Compose
from torch.utils.data import DataLoader

gt_transform = Compose([
    ToTensor()
    ])

gt_dataset_train = gtDatasetSampler2(gt_image_2, coords, transform=gt_transform) 
# gt_dl_train = DataLoader(gt_dataset_train, batch_size=5, shuffle=False)

len(gt_dataset_train), len(coords)
from matplotlib import pyplot as plt
plt.imshow(gt_dataset_train[0][0])
plt.show()
gt_dataset_train[1].shape<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12907844942211313, 'fraction_numerical': 0.01278510790631073, 'mean_word_length': 3.821499013806706, 'pattern_counts': {'":': 2, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '545114', 'license': 'MIT', 'n_tokens_mistral': 3211, 'n_tokens_neox': 3125, 'n_words': 841, 'path': 'week-06/ch07-oop-shortcuts.ipynb', 'repo_name': 'jlpalomino/oop-group', 'size': '9763'}