image

Nu har python3.10 släppts efter en period som beta. Jag tycker vi hittar en del intressanta nyheter och en sak som jag väntat på är switch-case syntax.

Vi har kunnat göra i princip samma sak med en massa if, elif, else statements, men det blir snabbt så rörigt. Med switch-case får vi mer lättläst kod.

match response.status_code:
    case 200:
        print("SUCCESS!")
    case 401:
        print("Autentiseringsfel")
    case 403:
        print("Verkar inte ha behörighet")
    case 500:
        print("Serverfel =(")
    case _:
        pass

switch/case med pattern matching

Vi ska dra samma exempel en nivå till. Vi kan lägga fler alternativ i samma case:

match response.status_code:
    case 200|201|202:
        print("SUCCESS!")
    case 401:
        print("Autentiseringsfel")
    case 403:
        print("Verkar inte ha behörighet")
    case 500:
        print("Serverfel =(")
    case _:
        pass

Eller till och med lägga till en range:

match response.status_code:
    case code if code < 299 and code > 200:
        print(f"SUCCESS {code}!")
    case 401:
        print("Autentiseringsfel")
    case 403:
        print("Verkar inte ha behörighet")
    case 500:
        print("Serverfel =(")
    case _:
        pass

Up to par?

Ja just att man i Python inte haft stöd för switch/case har nästan framstått som konstigt då det är ganska vanligt förekommande. Man har nästan tänkt att det blivit en principsak och det kanske det har varit. Nu när vi väl får switch/case och du kanske inte kodat i andra språk kanske du tycker att det är en liten sak men jag ska ge ytterligare ett exempel där vi verkligen får högre läsbarhet med switch/case.

Vi hämtar lite data från en ACI miljö med anropet:

GET: https://10.10.20.14/api/node/mo/topology/pod-1.json?query-target=children&target-subtree-class=fabricNode

{
    "totalCount": "4",
    "imdata": [
        {
            "fabricNode": {
                "attributes": {
                    "adSt": "on",
                    "address": "10.0.208.66",
                    "annotation": "",
                    "apicType": "apic",
                    "childAction": "",
                    "delayedHeartbeat": "no",
                    "dn": "topology/pod-1/node-102",
                    "extMngdBy": "",
                    "fabricSt": "active",
                    "id": "102",
                    "lastStateModTs": "2021-10-07T05:54:34.138+00:00",
                    "lcOwn": "local",
                    "modTs": "2021-10-07T05:56:23.377+00:00",
                    "model": "N9K-C9396PX",
                    "monPolDn": "uni/fabric/monfab-default",
                    "name": "leaf-2",
                    "nameAlias": "",
                    "nodeType": "unspecified",
                    "role": "leaf",
                    "serial": "TEP-1-102",
                    "status": "",
                    "uid": "0",
                    "vendor": "Cisco Systems, Inc",
                    "version": "simsw-4.2(3q)"
                }
            }
        },
        {
            "fabricNode": {
                "attributes": {
                    "adSt": "on",
                    "address": "10.0.208.64",
                    "annotation": "",
                    "apicType": "apic",
                    "childAction": "",
                    "delayedHeartbeat": "no",
                    "dn": "topology/pod-1/node-101",
                    "extMngdBy": "",
                    "fabricSt": "active",
                    "id": "101",
                    "lastStateModTs": "2021-10-07T05:53:06.730+00:00",
                    "lcOwn": "local",
                    "modTs": "2021-10-07T05:54:23.348+00:00",
                    "model": "N9K-C9396PX",
                    "monPolDn": "uni/fabric/monfab-default",
                    "name": "leaf-1",
                    "nameAlias": "",
                    "nodeType": "unspecified",
                    "role": "leaf",
                    "serial": "TEP-1-101",
                    "status": "",
                    "uid": "0",
                    "vendor": "Cisco Systems, Inc",
                    "version": "simsw-4.2(3q)"
                }
            }
        },
        {
            "fabricNode": {
                "attributes": {
                    "adSt": "on",
                    "address": "10.0.0.1",
                    "annotation": "",
                    "apicType": "apic",
                    "childAction": "",
                    "delayedHeartbeat": "no",
                    "dn": "topology/pod-1/node-1",
                    "extMngdBy": "",
                    "fabricSt": "unknown",
                    "id": "1",
                    "lastStateModTs": "1970-01-01T00:00:00.000+00:00",
                    "lcOwn": "local",
                    "modTs": "2021-10-07T05:45:31.959+00:00",
                    "model": "VMware Virtual Platform",
                    "monPolDn": "uni/fabric/monfab-default",
                    "name": "apic1",
                    "nameAlias": "",
                    "nodeType": "unspecified",
                    "role": "controller",
                    "serial": "TEP-1-1",
                    "status": "",
                    "uid": "0",
                    "vendor": "Cisco Systems, Inc",
                    "version": "4.2(3q)"
                }
            }
        },
        {
            "fabricNode": {
                "attributes": {
                    "adSt": "on",
                    "address": "10.0.208.65",
                    "annotation": "",
                    "apicType": "apic",
                    "childAction": "",
                    "delayedHeartbeat": "no",
                    "dn": "topology/pod-1/node-201",
                    "extMngdBy": "",
                    "fabricSt": "active",
                    "id": "201",
                    "lastStateModTs": "2021-10-07T05:54:00.139+00:00",
                    "lcOwn": "local",
                    "modTs": "2021-10-07T05:54:23.347+00:00",
                    "model": "N9K-C9508",
                    "monPolDn": "uni/fabric/monfab-default",
                    "name": "spine-1",
                    "nameAlias": "",
                    "nodeType": "unspecified",
                    "role": "spine",
                    "serial": "TEP-1-103",
                    "status": "",
                    "uid": "0",
                    "vendor": "Cisco Systems, Inc",
                    "version": "simsw-4.2(3q)"
                }
            }
        }
    ]
}

Use case exempel - sortera data

Låt oss säga att vi vill sortera miljön så att vi har leafs och spines i varsin lista och övriga komponenter i en egen lista.

Tidigare hade vi gjort så här:



new_dict = {
    "leaf": [],
    "spine": [],
    "other": []
}


for device in data['imdata']:
    role = device['fabricNode']['attributes']['role']
    name = device['fabricNode']['attributes']['name']
    dn = device['fabricNode']['attributes']['dn']
    if role == 'leaf':
        new_dict['leaf'].append({"dn": dn, "name": name})
    elif role == 'spine':
        new_dict['spine'].append({"dn": dn, "name": name})
    else:
        new_dict['other'].append({"dn": dn, "name": name})

print(new_dict)

Inte jättedrygt kanske, men kolla hur vi kan göra nu:

new_dict = {
    "leaf": [],
    "spine": [],
    "other": []
}


for device in data['imdata']:
    match device:
        case {"fabricNode": {"attributes": {"role": "leaf"|"spine" as role,
                                            "dn": dn,
                                            "name": name
                                            }
        }}:
            new_dict[role].append({"dn": dn, "name": name})

        case _:
            new_dict['other'].append({"dn": dn, "name": name})

print(new_dict)

Vad vi gör i det senare exemplet är flera saker samtidigt. Först kollar vi om role attributet är antingen “leaf” eller “spine”, om så är fallet sparar vi värdet till variablen role. Samtidigt passar vi på att mappa upp attributen “dn” och “name” till motsvarande variabler och lägger sedan in den här nya dictionaryn i vår response-dictionary.

Sist har vi ett typ av else-statement

case _:

Och det innebär att om ingenting annat matchat gör vi följande. Och i vårt fall använder vi samma attribut som i caset innan men lägger dictionaryn i listan “other”.

Jag gillar att vi inte behöver repetera oss, jag tycker att det blir enklare att läsa, förstå tanken med koden och framförallt mindre risk att ha sönder saker när man ska göra ändringar framöver. Jag kommer definitivt använda switch case framöver!

Det här är en liten kul nyhet som kom nu i version 3.10 som jag tror vi kommer se mer av, så oavsett om du gillar det eller inte tror jag att du bör bli familjär med syntaxen.


Senior Consultant


2025

Acebit expanderar

1 minute read

Acebit expanderar – automationsess från Dalarna öppnar i Stockholm

Back to Top ↑

2024

Acebit i Falu-Kuriren

less than 1 minute read

Även Falu-Kuriren har intresserat sig för Acebit och besökt oss i Falun!

Back to Top ↑

2023

Meraki API & Mgmt interface

4 minute read

Nyligen stötte jag på ett scenario som innebar att ca 200 Meraki-enheter behövde byta inställning från DHCP till statisk IP-adressering. Istället för att gör...

Arbeta med VPC Del3 - Konfiguration

3 minute read

I mina tidigare inlägg om virtuella port-channels kikade vi på vad det är och vilka delar de utgör. Det här avsnittet kommer beröra hur en grundkonfiguration...

Få upp farten med concurrency

3 minute read

Bakgrund Idag tänkt jag skriva några rader om att skriva concurrent kod, eller “samtidighet” om vi prompt ska översätta det till svenska. För att enklare för...

Back to Top ↑

2022

Back to Top ↑

2021

Back to Top ↑