# Chapter5.py ''' Factory -> Creators PROVIDERS -> api/input "provide or inject" into the app Services -> web services "logic" Classes -> Blueprint for objects attributes -> init on the class Objects -> objs in memory Functions -> isolate REUSABLE blocks of code DRY property / variable -> firstName as string value -> Bob ''' ''' ### Use variables to define a customer ### # variable in memory firstName = "Bob" # firstName as string assigned value Bob lastName = "Smith" fName, lName = "Jane", "Doe" # chapter 7 pythonic ''' ### Use a function to define a customer using property var ### def customer(age=21): age = age # variable = param passed firstName = "Bob" lastName = "Smith" fullName = firstName + " " + lastName # join operator constructing obj return fullName, age # call the function customerFullName, customerAge = customer() # Assigning the return to a variable print(customerFullName, customerAge) # testing Bob Smith, 21 ### Use a class to define a customer using attributes ### # pages 53-55 class Customer: # Best Practice to use TitleCase for class objects # Instead of using properties of an object, we are going to define attributes of a class ## happens On Initialization "aka at runtime init" ## it does NOT wait for assignment -> happens later ''' objName -> obj visible in memory _objName -> obj hidden in memory __Name__ -> attribute of a class ''' def __init__(self, firstName, lastName, age): # param1 (who/where) self -> "at the warehouse" cls -> "after delivery" # param2 ... (data constructed) # variables just have an objName # Properties are defined by "this".Name self.Name = or cls.Name = self.firstName = firstName self.lastName = lastName self.age = age # class attributes are not "RETURNED" aka using the return keyword like a function, they are created using a "new instance of" the class objects. There is no "call" of a class like we do with a function, BECAUSE the class was pre-built on initialization ### Application using a class ### ### probably coded somewhere else where main() statement is defined ### new instance of the class objects ### data set ### var_firstName = "Jane" # PythonLevel2_1113.Chapter5.prop.value var_lastName = "Doe" var_age = 29 ################ # initialize a new instance of an object based on a class ## = var assigned value ## now = object as new instance of class ## (tuple) is the constructor for the data customer1 = Customer(var_firstName, var_lastName, var_age) customer2 = Customer("Philip", "Matusiak", 29) print(customer2.firstName) # Philip # PythonLevel2_1113.Chapter5.Customer.Object.attr.value ### instance methods page 55, static methods page 57, class methods 57 ### class Product: # Global attrs # Initialized __init__ attrs # static methods (initialized attrs on class) # class methods (global attrs) # functions and instance methods (use anything) # Global attrs for the class taxRate = 0 # initially set to non taxable # instance method page 55 # initialize objs as attr of a class def __init__(self, name, price): # Product("widget 1", 52.50) self.name = name self.price = price # Product.product1.price<52.50> # static method page 57 # used as a way to "support" other functions and methods # we have an object and we want to apply something to that object WITHOUT changing the original object and then returning something new # function -> static method (add a decorator/annotator) @staticmethod # commonly don't use the self or cls for param1 def applyDiscount(price, discountRate): # 10 or .10 (1-.10) return price * (1 - discountRate) # 52.50 * .90 # we need to use that static method to update the price in the cart def updatePrice(self, discount): self.price = self.applyDiscount(self.price, discount) # there is no return keyword BECAUSE the self keyword is "returning the updated price to the class" # class method ## Global attr of a class (tax rate) ## aka "it is a function in a class". There is no instance object in memory and it is mutatable thru the instance name print(f"Product Name: {product1.name} - Original Product Price: ${product1.price:.2f}") # Use an EXISTING instance of a Product (product1) and use the static method product1DiscountedPrice = Product.applyDiscount(product1.price, .20) print(f"Product 1 Discounted Price: ${product1DiscountedPrice:.2f}") # product1 -> name, price, product1DiscountedPrice # initialize a Product Class AND use a method from that class at the same time product2DiscountedPrice = Product.applyDiscount(100, .10) print(f"Product 2 Discounted Price: ${product2DiscountedPrice:.2f}") # product2 -> product2DiscountedPrice # Tax rate examples ## Current tax rate = 0 -> Global attr cls.taxRate ### Tax Table ### ''' # Tax table in a dictionary taxTable = [ { "state": "Florida", "rate": .07 }, { "state": "Iowa", "rate": .05 } ] ''' taxable = "yes" state1, rate1 = "Florida", .07 state2, rate2 = "Iowa", .05 state = input("Enter your state: ") ''' product7 = Product("widget 7", 100) for state, rate in enumerate(taxTable): print("logic for product7 loop") ''' if (taxable == "no"): # Product is Non Taxable product3 = Product("Widget 3", 100) lineItemTotal3 = product3.price + product3.calculateTaxRate() # 100 ''' product3.price + product3.calculateTaxRate() 100 + self.price * Product.taxRate 100 + 100 * Product.taxRate current value for Product.taxRate<0> 100 + 100 * 0 -> 100 + 0 -> 100 ''' print(f"Product 3 Total with Tax: ${lineItemTotal3:.2f}") elif (taxable == "yes" and state == "Florida"): # class method that sets the new tax rate setTaxRate(pass the new value) Product.setTaxRate(rate1) # cls.taxRate = .07 print(f"Tax rate: {Product.taxRate * 100:.2f}%") # 7% product4 = Product("Widget 4", 100) lineItemTotal4 = product4.price + product4.calculateTaxRate() print(f"Product 4 Total with Tax: ${lineItemTotal4:.2f}") # 107.00 elif (taxable == "yes" and state == "Iowa"): # class method that sets the new tax rate setTaxRate(pass the new value) Product.setTaxRate(rate2) # cls.taxRate = .05 print(f"Tax rate: {Product.taxRate * 100:.2f}%") # 5% product5 = Product("Widget 5", 100) lineItemTotal5 = product5.price + product5.calculateTaxRate() print(f"Product 5 Total with Tax: ${lineItemTotal5:.2f}") # 105.00 else: Product.setTaxRate(0) print(f"Tax rate: {Product.taxRate * 100}%") # 0% # EOF