How to replace a lot of if/elif statements in python?

Question:

i am writing function in python for control outputs on QUIDO board throught post html requests. I have a lot of if and elif statements in my program. Is there some way how to make code more transparent? Quido board has 16 outputs so i have 16 if statements with some if/elif inside.

    def setOutput(output,action):
#Output 1
if output == 1:
    if action == 1:
        r = requests.get(' http://192.168.1.254/set.xml?type=s&id=1')
        print(r.url)
    elif action == 0:
        r = requests.get(' http://192.168.1.254/set.xml?type=r&id=1')
        print(r.url)
#Output 2        
if output == 2:
    if action == 1:
        r = requests.get(' http://192.168.1.254/set.xml?type=s&id=2')
        print(r.url)
    elif action == 0:
        r = requests.get(' http://192.168.1.254/set.xml?type=r&id=2')
        print(r.url)
if output == 3:
    if action == 1:
        r = requests.get(' http://192.168.1.254/set.xml?type=s&id=3')
        print(r.url)
    elif action == 0:
        r = requests.get(' http://192.168.1.254/set.xml?type=r&id=3')
        print(r.url)
if output == 4:
    if action == 1:
        r = requests.get(' http://192.168.1.254/set.xml?type=s&id=4')
        print(r.url)
    elif action == 0:
        r = requests.get(' http://192.168.1.254/set.xml?type=r&id=4')
        print(r.url)
while 1:
setOutput(1, 1)
myTimer(1)
setOutput(1, 0)
myTimer(1)
Asked By: Neo159

||

Answers:

Something like this should work.

def setOutput(output, action):
    assert isinstance(output, int)
    param_type = 's' if action == 1 else 'r'

    r = requests.get(f'http://192.168.1.254/set.xml?type={param_type}&id={output}')
    print(r.url)
Answered By: Peter

Most replies will involve some kind of string variables:

if action in [0, 1]:
    t = 's' if action else 'r'
    print(requests.get(f' http://192.168.1.254/set.xml?type={t}&id={output}').url)

Dictionaries may work if action values are well defined:

action_map = {
    0: 's'
    1: 'r'
}
print(
    requests.get(
        f' http://192.168.1.254/set.xml?type{action_map[action]}&id={output}'
    ).url
)
Answered By: Guy Gangemi

It looks like your goal is to send the appropriate arguments to the server based on the action and the output, where the action is mapped to type as follows

0 --> "r"
1 --> "s"

And the output is directly passed in as the id param.

In this scenario, you can get rid of the output check and just pass it in directly.

r = requests.get('http://192.168.1.254/set.xml?type=s&id={output}')

Now, you only need to figure out how to get the correct type, which you can do a simple if/else or build a dictionary to support new actions.

Answered By: MxLDevs

Dictionary helps a lot in these cases:

def setOutput(output,action):
    type_dict = {
        1: 's',
        0: 'r'
    }
    url = f'http://192.168.1.254/set.xml?type={type_dict[action]}&id={str(output)}'
    r = requests.get(url)
    print(r.url)

setOutput(1, 1)
setOutput(1, 0)
setOutput(2, 1)
setOutput(2, 0)

Output:

http://192.168.1.254/set.xml?type=r&id=1
http://192.168.1.254/set.xml?type=s&id=1
http://192.168.1.254/set.xml?type=r&id=2
http://192.168.1.254/set.xml?type=s&id=2
Answered By: LakshayGMZ

you can simplify it:

def setOutput(output,action):
    type = 's' if (action == 1) else 'r'
    print("http://192.168.1.254/set.xml??type={0}&id={1}".format(type,output))
Answered By: Verizz

Personal preference but a params dictionary is easier and obviates the need for string formatting which can get clumsy if it needs to be modified/extended. Also, ALWAYS check the HTTP status

import requests

action_map = {1: 's', 2: 'r'}
url = 'http://192.168.1.254/set.xml'

def setOutput(output, action):
    params = {'type': action_map.get(action), 'id': output}
    (r := requests.get(url, params=params)).raise_for_status()
    print(r.url)
Answered By: Vlad