# Chapter 7 Becoming Pythonic 82-89 # Priciple of Programming in Python # Framework / Resource Allocation / Readability # Variables # Python x = 7 y = 3 z = 4 v = False # Pythonic x, y, z, v = 7, 3, 4, False # Temp variable assignment # Python using temp variables a = "original" b = "abstract" print(a,b) temp = a print(a,b,temp) tempb = b print(a,b,temp, tempb) a = b print(a,b) # Pythonic no temp variables a,b = "original", "abstract" print(a,b) # "original", "abstract" a,b = b,a print(a,b) # "abstract", "original" # List comprehension page 82 # Python List l = [] # empty list in memory # .append() to assign value for x in range(10): l.append(x) # [0] x += 1 # [0,1,...] # control print(l) # Pythonic # Create the list, add all the elements to the list, store it lc = [ x + 1 for x in range(10) ] # no append() print(lc) # Dictionary Comprehension {key: value} page 84 # Collection {'fname': value} as List # key fname # values "Bob", "Mary", "Joe" # [ {'fname': 'Bob' }, {'fname': 'Mary' }, {'fname': 'Joe' } ] # Data names = ["Bob","Mary","Joe"] # Python # Create an empty dict fname_values = [] for name in names: fname_name = {'fname': name } fname_values.append(fname_name) # loop from controller to object print(fname_values) # [ {'fname': 'Bob' }, {'fname': 'Mary' }, {'fname': 'Joe' } ] # Pythonic # Create the list, add all the dict elements to the list, store it fname_values = [{'fname': name} for name in names ] print(fname_values) # Custom iterators page 85 # Python class NonPythonicIterable: def __init__(self, max): self.max = max # 5 range [0-4] len(5) def interate(self): # __iter__ # control variable num = 0 # condition while num < self.max: # num < 5 yield num num += 1 # yield no storing var use an increment not an operator # num + 1 addition operator for variables # create and instance of the class iterator = NonPythonicIterable(5) # [0,1,2,3] # not related to python syntax # test the itertor values for num in iterator.interate(): # ys is replacing a collection with an iterator object print(num) # Pythonic # replace interate() with __iter__ and __next__ class PythonicIterable: def __init__(self, max): self.max = max # 5 range [0-4] len(5) # control variable self.num = 0 def __iter__(self): return self # 1. removed the control num = 0 to __init__ # 2. removed operation to __next__ def __next__(self): if self.num < self.max: num = self.num self.num += 1 # increment return num # if for or while raise StopIteration # Program # create an instance of the PythonicIterable Class iterator = PythonicIterable(5) for n in iterator: # n is local variable in the for scope print(n)