geek_xed
geek_xed

Reputation: 175

How to avoid hard coding in if condition of python script

I am new to python. I have query regarding un-hardcoding object names(if condition) in python script. I have fruit = [ Apple, Mango, Pineapple, Banana, Oranges] and size = [ small, medium , big] Currently I write code as below:

if (fruit == apple, size == small): 
   statement 1
   statement 2
elif (fruit == apple, size == medium):
   statement 1
   statement 2
elif (fruit == apple, size == big):
   statement 1
   statement 2
elif (fruit == Mango, size == small):
   statement 1
   statement 2
elif (fruit == Mango, size = medium):
   statement 1
   statement 2

How can I avoid writing multiple if...else conditions?

Statement 1: Pulling up a dot file related to fruit and size from directory The path structure is main-directory/fruit/collateral/fruit_size.dot statement 2: Pulling up a txt file related to fruit and size from directory The path structure is main-directory/source/readparamters/readparam/fruit_size.txt

I want to execute statements for each condition one at a time. Currently I take inputs for fruit and size from user. Is there a way in python that the script can automatically take combinations one by one and execute statements? I know it's somewhat complex and python expert can help me.

Upvotes: 3

Views: 3358

Answers (6)

satomacoto
satomacoto

Reputation: 11973

How about using itertools.product and handling errors with try..catch. https://docs.python.org/3/library/itertools.html#itertools.product

import itertools

fruits = ['Apple', 'Mango', 'Pineapple', 'Banana', 'Oranges']
sizes = ['small', 'medium', 'big']

for fruit, size in itertools.product(fruits, sizes):
    dot_file = 'main-directory/{fruit}/collateral/{fruit}_{size}.dot'.format(fruit=fruit, size=size)
    text_file = 'main-directory/source/readparamters/readparam/{fruit}_{size}.txt'.format(fruit=fruit, size=size)
    try:
        open(dot_file)  # statement 1
        open(text_file)  # statement 2
    except Exception as e:
        print(e)  # handle erorrs!

Or, check file existence os.path.isfile without using try..catch.

import os
..
    dot_file = ..
    text_file = ..
    if os.path.isfile(dot_file):
        open(dot_file)  # statement 1
    if os.path.isfile(text_file):
        open(text_file)  # statement 2

itertools.product generates cartesian product of input iterables.

>>> fruits = ['Apple', 'Mango', 'Pineapple', 'Banana', 'Oranges']
>>> sizes = ['small', 'medium', 'big']
>>> list(itertools.product(fruits, sizes))
[('Apple', 'small'), ('Apple', 'medium'), ('Apple', 'big'), ('Mango', 'small'), ('Mango', 'medium'), ('Mango', 'big'), ('Pineapple', 'small'), ('Pineapple', 'medium'), ('Pineapple', 'big'), ('Banana', 'small'), ('Banana', 'medium'), ('Banana', 'big'), ('Oranges', 'small'), ('Oranges', 'medium'), ('Oranges', 'big')]

Upvotes: 1

Nishant Roy
Nishant Roy

Reputation: 1141

Python doesn't have switch cases unfortunately, but you can use a dictionary like the accepted answer to this question:

Replacements for switch statement in Python?

Upvotes: 0

Ajoy
Ajoy

Reputation: 1848

If all the file names can be generated using just the fruit names and sizes:

def process_fruits(fruit, size, param):
    dot_file = "main-directory/{fruit_name}/collateral/{size}.dot"
    text_file = "main-directory/source/readparamters/{param}/{size}.txt"

    fruit = dict(fruit_name=fruit, size=size, param=param)

    paths = dict(dot=dot_file.format(**fruit), text=text_file.format(**fruit))

    # load paths['dot']
    # load paths['text']

You can add this to a function, to get the paths whenever a fruit is created.


fruits = ['apple', 'mango']

for fruit in fruits:
    for size in ['small', 'medium', 'big']:
        process_fruits(fruit, size, 10)

Upvotes: 0

Nayuki
Nayuki

Reputation: 18542

(My first answer)

You can combine all the tests into one condition:

if (fruit == apple and (size == small or size == medium or size == big)) or \
        (fruit == Mango and (size == small or size == medium)):
    statement 1
    statement 2

(My second answer after the original poster made clarifications)

Write a loop to check if the condition is met, then execute the statements.

fruit = (...)  # From input
size  = (...)  # From input

found = False
known_fruits = ["apple", "mango"]  # Can be customized
known_sizes = ["small", "medium", "large"]  # Can be customized
for fr in known_fruits:
    for sz in known_sizes:
        if fruit == fr and size == sz:
            found = True
if found:
    statement 1
    statement 2

Upvotes: 2

nick_v1
nick_v1

Reputation: 1664

You can create a map of values and functions. For example

MAP = {'apples':{'small':function1,
                'large':function3},
      'oranges':{'small':function2}}
#Then Run it like so:
fruit = 'apples'
size = 'large'
result = MAP[fruit][size]()

That will look up the function for you in the dictionary using fruit and size then and run it and store output in result. This way, if you need to add additional fruit or sizes you can simply modify the data in the dictionary without altering any code.

EDIT: I just read your update. If processing steps are the same and the only thing that changes is the location of the file, I would suggest to write a function that takes fruit and size as arguments and opens the file based on input. Then you can run it with your desired fruit and sizes and not have a crazy if statement.

Upvotes: 7

Jerska
Jerska

Reputation: 12032

It really depends on what you have as statement 1 and statement 2.
One thing that works if the code is similar is to extract all the changing constants into a container, and use a dict to access them.

fruits = {
  'mango': {'color': 'orange'},
  'apple': {'color': 'red'},
   # ...
}
weights = {
  'apple': {
    'small': 100,
    'medium': 200,
    # ...
  }
  # ...
}

fruit = 'apple'
size = 'medium'

print "A %s %s is %s and weighs %ig" % (size, fruit, fruits[fruit]['color'], weights[fruit][size])
# => A medium apple is red and weighs 200g

Upvotes: 0

Related Questions