How to use a variable number of MULTIPLE arguments in Python (e.g. a function w/ 4 inputs)

55 Views Asked by At

I am wondering how I can approach this; I have a function I've written with 4 inputs. However, I need to apply this function to many different combinations of 4 inputs (with the number of combinations being varied each time), and sum the outputs. I will attach part of my code, but for example, say my code takes arguments "chemical," "acres," "amountperacre," and "units." I would like to be able to simultaneously run the code for multiple chemicals (that are linked to the following 3 variables) at a time and write for the resulting "MTCO2e" to be summed so that I don't have to run the code 50 times, record, the output of each run, and then sum them all. How might I go about this/is this possible? I've been doing a lot of reading about multiple arguments but am having trouble/confusion applying what I've read. Right now my code (which I am still building) looks like this. It works for individual chemicals, but I don't know how to synthesize it into one joint code that can sum the result of the MTCO2e's. Thank you!!

def chemicalemissions(chemical, acres, amountperacre, units):
         .
         .
         defining varibables, etc.
         .
         .
    #Cayuse Plus info
    #density units = lb/gal
    cayuseplusdenisty = 10.26
    activeingredientcayuseplus = .25
    if chemical == 'Cayuse Plus':
        densitykg = cayuseplusdenisty * lbstokg
        #gives density in kg/gal
        if units == 'gal':
            densitykg = densitykg
        #gives density in kg/fl oz
        if units == 'fl oz':
            densitykg = densitykg * galtofloz
        #total kg of product applied
        totalamountappliedkg = densitykg * amountperacre * acres
        #total kg active ingredient
        totalkgactiveingredient = totalamountappliedkg * activeingredientcayuseplus
        #total MJ required
        totalMJ = MJgeneral * totalkgactiveingredient
        #MTCO2e
        MTCO2e = totalMJ * kgCO2perMJperkgactiveingredient * kgCO2etoMTCO2e
        print(MTCO2e)
        
        
    #Tri-Fol info
    #density units = lbs/gal
    trifoldensity = 10.1
    trifolactiveingredient = .25
    if chemical == 'Tri-Fol':
        densitykg = trifoldensity * lbstokg
        #gives density in kg/gal
        if units == 'gal':
            densitykg = densitykg
        #gives density in kg/fl oz
        if units == 'fl oz':
            densitykg = densitykg * galtofloz
        #total kg of product applied
        totalamountappliedkg = densitykg * amountperacre * acres
        #total kg active ingredient
        totalkgactiveingredient = totalamountappliedkg * trifolactiveingredient
        #total MJ required
        totalMJ = MJgeneral * totalkgactiveingredient
        #MTCO2e
        MTCO2e = totalMJ * kgCO2perMJperkgactiveingredient * kgCO2etoMTCO2e

As for what I've tried I've experimented with *arg, but it seems like that is meant to be for one variable type? Like for example, multiple integers. But I'm not sure I can apply it to the types of variables I have.

1

There are 1 best solutions below

0
dafrandle On

given the context that your provided in response to my comment and if this is not supposed to be quick and dirty it would probably be best to make a class structure for the chemicals like this rather than using a function with parameters.

here is how you might do it:

# define your unit conversion globals
lbstokg = 2.205
galtofloz = 128
# i have no idea what these below are
MJgeneral = 1337
kgCO2perMJperkgactiveingredient = 69
kgCO2etoMTCO2e = 420


class Chemical:  # this is the parent class which contains universal variables
    def __init__(self, name, acres, amountperacre, units):
        self.name = name
        self.acres = acres
        self.amountperacre = amountperacre
        self.units = units

    def get_emissions(self):
        raise NotImplementedError('Can not call this on parent class')


# as each chemical seems to have a different calculation necessary to get the emissions we will make a child class for each chemical

class CayusePlus(Chemical):
    def __init__(self, acres, amountperacre, units):
        name = 'Cayuse Plus'
        super().__init__(name, acres, amountperacre, units)  # this calls the __init__ function as defined in the parent class

        # add unique data for this chemical:
        self.density_in_lbs = 10.26
        self.density_in_kg = self.density_in_lbs * lbstokg
        self.active_ingredient = .25

    def get_emissions(self):
        density_factor = 0
        if self.units == 'gal':
            density_factor = self.density_in_kg
        elif self.units == 'fl oz':
            density_factor = self.density_in_kg * galtofloz

        total_applied = density_factor * self.amountperacre * self.acres
        total_active_ingredient = total_applied * self.active_ingredient
        total_mj = MJgeneral * total_active_ingredient
        return total_mj * kgCO2perMJperkgactiveingredient * kgCO2etoMTCO2e

#-------------------------------------------------------------------------------------------------------------------
# now when you load the data we will create a instance of each class and store them in a list.
# since you said you are coming from excel I have assumed your data will be in csv format.

lines = [('chemical_name_1', 'acres', 'amountperacre', 'units'),
         ('chemical_name_2', 'acres', 'amountperacre', 'units')]
# you did not include how you have your data staged, so I have assumed you have read the file into a list of tuples

chemical_list = []

for line in lines:
    if line[0] == "Cayuse Plus":
        chemical_list.append(CayusePlus(line[1], line[2], line[3]))
    elif line[0] == "Other Chemical":
        chemical_list.append(OtherChemical(line[1], line[2], line[3]))
    # and so on

# now that we have our list made we can just loop though it
MTCO2e_list = []

for chemical in chemical_list:
    MTCO2e = chemical.get_emissions()
    print(f"{chemical.name} - MTCO2e: {MTCO2e}") # note: f strings allow you to easily embed data into a string - you need python3.6 or newer for these to work
    MTCO2e_list.append(float(MTCO2e))

print(f"Sum: {sum(MTCO2e_list)}")

This format will allow you to extend the functionality of your (assumed) reporting application more easily than if it was all in a singular massive function.

This is just a minimal example - and there are many ways to improve upon what is shared here. Hopefully this gives you enough ideas to arrive at a better solution though.

If you do only need a quick and dirty solution: just continue as you have done but instead of ending the function with print(MTCO2e) use return MTCO2e
Then in your loop where you are calling chemicalemissions() you just assign it to a variable like result = chemicalemissions().
You can now manipulate the result as you like - including appending each one to a list and then sum()ing the list after you have finished looping through the data.