Meer

Het if else-statement gebruiken in Python Parser of Field Calculator in ArcGIS for Desktop?

Het if else-statement gebruiken in Python Parser of Field Calculator in ArcGIS for Desktop?


Ik heb hulp nodig bij het schrijven van het python-script in de veldcalculator. Ik heb drie velden namelijk: CODE COMPLEX Map1

Map1 is een leeg veld dat ik wil invullen. Ik heb een aantal voorwaarden waaraan ik moet voldoen in een enkel Map1-veld. bijv. Als CODE 1.1.7 is en COMPLEX 4 is, dan zou de uitvoer voor Map1 1.3 moeten zijn, en deze voorwaarden gaan verder met verschillende CODE- en COMPLEX-waarden. Ik heb geprobeerd het zo te schrijven, maar het lukt niet:

Parser Python

Codeblok

def Reclass( !CODE! , !COMPLEX! ): if ( !CODE! == 1.1.7 en !COMPLEX! == 4): retourneer 1.3 elif ( !CODE! == 3.2.0 en !COMPLEX! == 4 ): return 1.3 else: return 0

Kaart1 =

Opnieuw classificeren( !CODE! , !COMPLEX!)

Kan iemand mij vertellen waar ik een fout maak? Of een andere manier om het te doen?


Het probleem zit in je codeblok.

In plaats van:

def Reclass( !CODE! , !COMPLEX! ): if ( !CODE! == 1.1.7 en !COMPLEX! == 4): retourneer 1.3 elif ( !CODE! == 3.2.0 en !COMPLEX! == 4 ): retour 1.3 anders: retour 0

proberen:

def Reclass( CODE , COMPLEX ): if ( CODE == "1.1.7" en COMPLEX == 4): return 1.3 elif ( CODE == "3.2.0" en COMPLEX == 4): return 1.3 else: return 0

De uitroeptekens zijn nodig in uw uitdrukking omdat ze daar veldnamen aangeven, maar in het codeblokCODEenCOMPLEXzijn Python-variabelen en kunnen worden genoemdeenenBals je wilt.

Het andere probleem is dat uw CODE-veld van het type tekst lijkt te zijn, dus ik heb aanhalingstekens toegevoegd rond de tests van de waarden. Ik kan niet zeggen of uw Map1- en COMPLEX-velden tekst of cijfers zijn, dus ik heb ze daar niet geplaatst - misschien moet u dat doen!


Python If-functie voor veldbereik

Eigenlijk is dit een Python in GIS, dus ik gebruik de tabel in mijn Arcgis en probeer het veld te tellen en te verdelen door categorie te gebruiken.

Ik heb Veld genaamd Verhoging de gegevens bevatten integer voorbeeld:
1 - 2
3 - 6
2 - 3
8.5 - 12
11 - 12

Ik moet het categoriseren met behulp van regel dat
als hoogte < 1 dan index = 0,3, als hoogte = 2 - 3 index = 0,6, als hoogte > 3 index = 1

mijn vraag is hoe ik het kan strippen en het kan categoriseren met behulp van mijn bovenstaande regel? Alvast bedankt


Je schrijft je functies verkeerd. Zorg ervoor dat u in de veldcalculator 'Toon codeblok' aanvinkt, zodat de Pre-logische scriptcode vak verschijnt. Schrijf in het vak Pre-Logic uw functie-

en dan in het vak eronder, waar staat de veldnaam = u moet de naam van de functie en de veldwaarde die u eraan doorgeeft, tussen uitroeptekens schrijven. Dus als je functie hierboven calcValue heet, zou je schrijven

Zonder een afbeelding te zien van hoe uw veldcalculator eruitziet, vermoed ik dat @csterling waarschijnlijk gelijk heeft. Een alternatief is echter om gewoon op attribuut te selecteren waarbij "mamerMN" <= 0.151560 , en vervolgens veld Bereken uw geselecteerde objecten op de normale manier naar 1 zonder dat een codeblok nodig is.


4 antwoorden 4

Bedankt dat je dit ter sprake hebt gebracht - ik heb ook een hogere frequentie opgemerkt van vragen met gemarkeerde veldcalculators. Ik geloof dat elke vraag met betrekking tot een GIS-veldcalculator on-topic is. De veldcalculator heeft zijn eigen bijzonderheden, zoals het inpakken van velden in !FieldName! voor ArcGIS. Met dit gezegd, zelfs de meest pure Python-concepten worden GIS-concepten, omdat ze nu softwarespecifieke vereisten hebben. Ik wil er ook aan toevoegen dat vragen over veldcalculators het afgelopen jaar meer routinematig zijn gemarkeerd, wat suggereert dat de vlaggen afkomstig kunnen zijn van een of enkele individuen, niet van de gemeenschap als geheel.

Ik vraag me af of de oplossing is om te zoeken naar de vroegste Python Parser van de Field Calculator-vraag en deze uitgebreid te bewerken om een ​​Community Wiki Q&A te worden met de titel Gebruik je de Python Parser van de Field Calculator van ArcGIS for Desktop? dat begint iets in de trant van:

Dit is een Community Wiki Q&A die bedoeld is om alle aspecten van het gebruik van de Python Parser van de Field Calculator van ArcGIS for Desktop te behandelen die niet pure Python.

Pure Python-vragen die verder gaan dan de voorbeelden voor beginners die als antwoorden hieronder worden gegeven, moeten worden onderzocht / gevraagd bij Stack Overflow.

Antwoorden kunnen variëren van het verwijderen van return/newline ( ) karakter uit Field met behulp van Python en Field Calculator?, tot een van de andere eigenaardigheden, zoals velden in uitroeptekens plaatsen (!FieldName!), en tot enkele van de meest gestelde "beginners" Python"-tips die uit alle Q&As komen die we tot nu toe hebben gezien.

Kandidaten voor de "beginnersvragen" om te proberen te verbergen, kunnen afkomstig zijn van deze FAQ.

De bedoeling zou zijn om alle toekomstige Python Parser-beginnersvragen terug te verwijzen naar deze als duplicaten, en om alle complexe vragen met betrekking tot de Field Calculator om te leiden die toch pure Python zijn om te onderzoeken/vragen bij Stack Overflow.

Een vergelijkbare benadering zou kunnen worden gebruikt om een ​​Community Wiki te maken voor het gebruik van Python met de Field Calculator van QGIS.

Het doel van het maken van deze Canonical Q&A's is om te voorkomen dat de community steeds weer vergelijkbare vragen moet beantwoorden, wat weinig nieuwe waarde toevoegt en betekent dat bezoekers van de site door mogelijk honderden Q&A's moeten waden in plaats van een enkele zeer goed schriftelijke Q&A van de community over het onderwerp.

Dit is een van mijn favoriete soorten vragen en ik ben persoonlijk teleurgesteld als ze worden gesloten als off-topic. De Python-vragen zullen nooit stoppen, dus GIS SE kan zich net zo goed aanpassen in plaats van ze af te wijzen.

Hier is mijn voorstel voor een nieuwe vraag die moet worden aangeduid als de veelgestelde vragen over het berekenen van canonieke velden. Ik dacht dat ik het hier zou voorstellen in plaats van op de hoofdsite, zodat het kan worden verfijnd en besproken. Ik zou ook willen voorstellen om een ​​nieuwe vraag te maken in plaats van een bestaande vraag een nieuwe bestemming te geven, zodat we volledige controle hebben over de inhoud ervan (in feite een onbeschreven blad).


1 antwoord 1

Open een Python-console en voer de volgende regel uit:

re.search(r"""((.*?))""", "Witless Bay (1001559) T 00000 ( 6,5%)")

Je zult zien dat het een match-object retourneert ( <_sre.SRE_Match object op 0x15AB2E60> ) zoals @mikewatt opmerkte.

ArcGIS kan dit object op geen enkele manier in een veld invoegen. Je moet de groepsmethode gebruiken.

Door het voorgaande voorbeeld te volgen, hebt u toegang tot de groepen, afhankelijk van uw resultaat. In dit geval kun je slechts twee groepen krijgen en (ik neem aan) je bent geïnteresseerd in de tweede:


6.1. Meer over modules¶

Een module kan zowel uitvoerbare instructies als functiedefinities bevatten. Deze instructies zijn bedoeld om de module te initialiseren. Ze worden uitgevoerd alleen de eerst keer dat de modulenaam wordt aangetroffen in een importinstructie. 1 (Ze worden ook uitgevoerd als het bestand als script wordt uitgevoerd.)

Elke module heeft zijn eigen privé-symbooltabel, die wordt gebruikt als de algemene symbooltabel door alle functies die in de module zijn gedefinieerd. De auteur van een module kan dus globale variabelen in de module gebruiken zonder zich zorgen te maken over toevallige botsingen met de globale variabelen van een gebruiker. Aan de andere kant, als je weet wat je doet, kun je de globale variabelen van een module aanraken met dezelfde notatie die wordt gebruikt om naar zijn functies te verwijzen, modname.itemname .

Modules kunnen andere modules importeren. Het is gebruikelijk maar niet verplicht om alle import statements aan het begin van een module (of script, wat dat betreft) te plaatsen. De geïmporteerde modulenamen worden in de algemene symbooltabel van de importerende module geplaatst.

Er is een variant van de importinstructie die namen uit een module rechtstreeks importeert in de symbooltabel van de importerende module. Bijvoorbeeld:

Dit introduceert niet de modulenaam waaruit de imports worden gehaald in de lokale symbooltabel (dus in het voorbeeld is fibo niet gedefinieerd).

Er is zelfs een variant om alle namen te importeren die een module definieert:

Hiermee worden alle namen geïmporteerd, behalve de namen die beginnen met een onderstrepingsteken ( _ ). In de meeste gevallen gebruiken Python-programmeurs deze faciliteit niet omdat het een onbekende reeks namen in de interpreter introduceert, waardoor mogelijk enkele dingen worden verborgen die u al hebt gedefinieerd.

Merk op dat in het algemeen de praktijk van het importeren van * uit een module of pakket wordt afgekeurd, omdat dit vaak slecht leesbare code veroorzaakt. Het is echter prima om het te gebruiken om typen in interactieve sessies op te slaan.

Als de modulenaam wordt gevolgd door als , dan is de naam die volgt op as rechtstreeks gebonden aan de geïmporteerde module.

Dit is in feite het importeren van de module op dezelfde manier als import fibo zal doen, met als enige verschil dat het beschikbaar is als fib .

Het kan ook worden gebruikt bij gebruik van met vergelijkbare effecten:

Omwille van efficiëntieredenen wordt elke module slechts eenmaal per tolksessie geïmporteerd. Daarom moet u, als u uw modules wijzigt, de interpreter opnieuw opstarten - of, als het slechts één module is die u interactief wilt testen, gebruik importlib.reload() , b.v. import importlib importlib.reload(modulenaam) .

6.1.1. Modules als scripts uitvoeren¶

Wanneer u een Python-module uitvoert met

de code in de module wordt uitgevoerd, net alsof je het hebt geïmporteerd, maar met de __name__ ingesteld op "__main__" . Dat betekent dat door deze code aan het einde van je module toe te voegen:

je kunt het bestand zowel bruikbaar maken als een script als als een importeerbare module, omdat de code die de opdrachtregel ontleedt alleen wordt uitgevoerd als de module wordt uitgevoerd als het "hoofd" -bestand:

Als de module is geïmporteerd, wordt de code niet uitgevoerd:

Dit wordt vaak gebruikt om een ​​handige gebruikersinterface voor een module te bieden, of voor testdoeleinden (door de module als een script uit te voeren, wordt een testsuite uitgevoerd).

6.1.2. Het modulezoekpad¶

Wanneer een module met de naam spam wordt geïmporteerd, zoekt de interpreter eerst naar een ingebouwde module met die naam. Als het niet wordt gevonden, zoekt het naar een bestand met de naam spam.py in een lijst met mappen die wordt gegeven door de variabele sys.path . sys.path wordt geïnitialiseerd vanaf deze locaties:

De map met het invoerscript (of de huidige map als er geen bestand is opgegeven).

PYTHONPATH (een lijst met directorynamen, met dezelfde syntaxis als de shellvariabele PATH ).

De installatie-afhankelijke standaard.

Op bestandssystemen die symlinks ondersteunen, wordt de map met het invoerscript berekend nadat de symlink is gevolgd. Met andere woorden, de map met de symbolische link is niet toegevoegd aan het zoekpad van de module.

Na initialisatie kunnen Python-programma's sys.path wijzigen. De map met het script dat wordt uitgevoerd, wordt aan het begin van het zoekpad geplaatst, vóór het standaard bibliotheekpad. Dit betekent dat scripts in die directory worden geladen in plaats van modules met dezelfde naam in de bibliotheekdirectory. Dit is een fout tenzij de vervanging bedoeld is. Zie de sectie Standaardmodules voor meer informatie.

6.1.3. "Gecompileerde" Python-bestanden¶

Om het laden van modules te versnellen, slaat Python de gecompileerde versie van elke module op in de __pycache__ directory onder de naam module. versie .pyc , waar de versie het formaat van het gecompileerde bestand codeert, bevat het over het algemeen het Python-versienummer. In CPython release 3.3 zou de gecompileerde versie van spam.py bijvoorbeeld in de cache worden opgeslagen als __pycache__/spam.cpython-33.pyc . Door deze naamgevingsconventie kunnen gecompileerde modules van verschillende releases en verschillende versies van Python naast elkaar bestaan.

Python controleert de wijzigingsdatum van de broncode ten opzichte van de gecompileerde versie om te zien of deze verouderd is en opnieuw moet worden gecompileerd. Dit is een volledig automatisch proces. Bovendien zijn de gecompileerde modules platformonafhankelijk, zodat dezelfde bibliotheek kan worden gedeeld tussen systemen met verschillende architecturen.

Python controleert de cache niet in twee gevallen. Ten eerste wordt het altijd opnieuw gecompileerd en wordt het resultaat niet opgeslagen voor de module die rechtstreeks vanaf de opdrachtregel is geladen. Ten tweede controleert het de cache niet als er geen bronmodule is. Om een ​​niet-bron (alleen gecompileerde) distributie te ondersteunen, moet de gecompileerde module in de brondirectory staan ​​en mag er geen bronmodule zijn.

U kunt de schakelopties -O of -OO op de Python-opdracht gebruiken om de grootte van een gecompileerde module te verkleinen. De schakeloptie -O verwijdert assert-statements, de -OO-switch verwijdert zowel assert-statements als __doc__-strings. Aangezien sommige programma's erop kunnen vertrouwen dat deze beschikbaar zijn, moet u deze optie alleen gebruiken als u weet wat u doet. “Geoptimaliseerde” modules hebben een opt-tag en zijn meestal kleiner. Toekomstige releases kunnen de effecten van optimalisatie veranderen.

Een programma werkt niet sneller wanneer het wordt gelezen uit een .pyc-bestand dan wanneer het wordt gelezen uit een .py-bestand. Het enige dat sneller is aan .pyc-bestanden is de snelheid waarmee ze worden geladen.

De module compileall kan .pyc-bestanden maken voor alle modules in een map.

Er is meer detail over dit proces, inclusief een stroomschema van de beslissingen, in PEP 3147.


Trainingscursus ArcGIS voor ruimtelijke analyse

ArcGIS* is een geografisch informatiesysteem voor het werken met kaarten en geografische informatie. Gebruik en implementeer algemene GIS-technieken in ArcGIS om ruimtelijke gegevensprojecten te creëren.

Deze door een instructeur geleide, live training (online of op locatie) is bedoeld voor veldecologen en natuurbeschermingsmanagers die ruimtelijke gegevensprojecten in ArcGIS willen creëren.

Aan het einde van deze training zijn de deelnemers in staat om:

  • Voer ruimtelijke gegevens uit als visualisaties, zoals kaarten.
  • Voer geostatica uit op actuele gegevens.
  • Implementeer ruimtelijke data-analyse, dataverwerking en mapping met ArcGIS.
  • Analyseer ruimtelijke gegevens voor projecten in ArcGIS.

Formaat van de cursus

  • Interactieve lezing en discussie.
  • Veel oefeningen en oefeningen.
  • Hands-on implementatie in een live-lab omgeving.

Opties voor cursusaanpassing

  • Wat is GIS?
  • ArcGIS-versies
  • Lagen, attributen, objecten, selecties en attributentabellen

Geospatiale en ruimtelijke gegevens

De ontwikkelomgeving voorbereiden

ArcGIS en zijn functionaliteiten

  • Ruimtelijke data toepassen en visualiseren
  • Kenmerken en waarden identificeren
  • Selecties maken
  • Zoomen en meten
  • ShapeFile-geometrie gebruiken
  • Werkende coördinatensystemen
  • ArcCatalog gebruiken
  • Metagegevens wijzigen
  • Rasters weergeven
  • Rasters samenvoegen
  • Rasters opnieuw bemonsteren en opnieuw classificeren
  • Een raster knippen
  • Rasterwaardepunten extraheren
  • Een raster geo-referentie
  • ShapeFile-kenmerken gebruiken
  • Ruimtelijke samenvoeging met tabelgegevens
  • Choropletenkaarten maken
  • Nieuwe gegevensbestanden implementeren
  • Nieuwe functies tekenen
  • Punten plotten
  • Gegevens samenvoegen
  • Gegevens knippen
  • Buffers maken

Finalisaties en optimalisaties

  • Kaartlay-outs gebruiken
  • Werken met een locatiekaart
  • Legenda's maken
  • Schaalbalken en titels implementeren
  • Kaarten exporteren en afdrukken

*ArcGIS is een handelsmerk, servicemerk en geregistreerd merk van Esri in de Verenigde Staten, de EU en andere internationale rechtsgebieden. Esri heeft deze training niet beoordeeld op volledigheid, nauwkeurigheid of kwaliteit, en als zodanig onderschrijft, sponsort of sluit ze zich niet aan bij deze training.


Deel 2: Werken met Social Explorer

Gegevens, gegevens, gegevens!

Laten we het hebben over gegevensmanipulatie in ArcMap, een van de kernfuncties van elk GIS-programma. Binnen ArcMap is “joining” of “connecting” data een fundamentele taak voor het werken tussen data uit verschillende bronnen. Er zijn twee basis “joining” methodes beschikbaar:

  1. Deelnemen aan – een externe gegevensbron verbinden met een GIS-gegevensset
  2. Spatial Join – verbindt gegevens op basis van geografie

Deze workshop richt zich op de eerste methode “joining”, die meer toepasbaar is op niet-geografische datasets, zoals Excel-spreadsheets, CSV's en andere datatabellen.

Gegevens verkrijgen

Social Explorer levert gegevens voor de gehele US Census (1790 tot 2010) en de American Community Survey (2005 tot 2015).

Bekijk dit eens!

Laten we werkgelegenheidsgegevens downloaden van Social Explorer:

  1. Ga naar Social Explorer en klik op de “Tafels” tabblad
  2. Selecteer “American Community Survey (5-jarige schattingen)'8221
  3. Klik op “Rapport starten” voor de nieuwste enquête
  4. Selecteer “district” voor geografisch type, markeer “alle provincies” en klik op de “Toevoegen” knop, en klik vervolgens op “Ga verder naar Tabellen
  5. Klik op de “Selecteer op trefwoord” tabblad en voer “ . inwerkgelegenheid
  6. Markeer “T33. Arbeidsstatus voor totale bevolking van 16 jaar en ouder” en klik op “Toevoegen” en dan “Toon resultaten
  7. Klik op de koptekst voor de tabel om naar de Data Dictionary-pagina te gaan die deze gegevens beschrijft. Dit opent in een nieuw venster. Houd dit venster open, we komen er later op terug.
  8. Ga terug naar de rapportpagina en klik op de “Gegevens downloaden” tabblad
  9. Klik op de “Provinciegegevens (CSV)” link om de gegevens naar uw projectmap te downloaden. Noem het bestand “werkgelegenheid.csv

Importeer de gegevens in ArcMap

Laten we deze nieuwe werkgelegenheidstabel importeren in ArcMap.

  1. Klik op de gegevens toevoegen knop en importeer de werkgelegenheid.csv tafel
  2. Klik met de rechtermuisknop op de tabel (uit de inhoudsopgave in het linkerdeelvenster) en ga naar '8220'eigenschappen
  3. Standaard maakt social explorer veel kolommen aan, waarvan we er veel niet nodig hebben. Klik op de “alles uitvinken” knop (ziet eruit als een leeg vel papier), en selecteer de volgende velden:
    1. Geo_FIPS
    2. Geo_NAME
    3. SE_T033_001
    4. SE_T033_002
    5. SE_T033_003
    6. SE_T033_004
    7. SE_T033_005
    8. SE_T033_006
    9. SE_T033_007

    De leidende nul-nachtmerrie…

    Open de attributentabel voor uw werkgelegenheidstabel. Let op de kolom Geo_FIPS. Het eerste record is voor Autauga County in Alabama. De Geo_FIPS is �”. De “real” FIPS-code voor Autauga County is echter �” (met als leidende 𔄘'8221). Arc interpreteert de kolom als numeriek en snijdt daarom alle voorloopnullen in de kolom bij. Dit vormt een probleem wanneer we deze kolom moeten gebruiken om de gegevens samen te voegen met een andere laag met dezelfde FIPS-code. De volgende python-code lost dit probleem op door een nieuwe kolom te maken en de voorloopnullen toe te voegen:

    1. Klik op de menuknop van de tabel en klik op “Veld toevoegen…
    2. Noem het nieuwe veld “FIPS“, type “Tekst“, en lengte “5
    3. Klik in de tabelweergave met de rechtermuisknop op de nieuwe kolomkop en klik op '8220'Veldcalculator
    4. Kies in de veldcalculator de parser “Python'8221 en voer de volgende formule in: str( !Geo_FIPS! ).zfill(5)

    Gegevens samenvoegen

    Nu zijn we klaar om onze werkgelegenheidsgegevens toe te voegen aan onze provincielaag.

    1. Klik met de rechtermuisknop op “us_counties“, “Verbindt en relateert“, “Doe mee'
    2. Kies “FIPS” als het veld om mee te doen, selecteer de “werkgelegenheid” tafel, en kies ook “FIPS” om de join op te baseren.
    3. Klik met de rechtermuisknop op “us_counties” en ga naar “Eigenschappen“, “symboliek“. Herinnert u zich nu het tabblad Gegevenswoordenboek dat u opende toen u de gegevens uit Social Explorer downloadde? Hier komt het van pas, aangezien de gegevensvelden niet beschrijvend zijn. Voor het geval je het tabblad bent kwijtgeraakt, hier is het nog een keer:
    4. Laten we het werkloosheidspercentage van het land in kaart brengen. Voor “Waarde“, selecteer “werkloos“, of “SE_T033_006“.
    5. Laten we ook de gegevens normaliseren door de inzetbare populatie. Voor “Normalisatie“, selecteer “Bevolking van 16 jaar en ouder“, of “SE_T033_001
    6. De arbeidsparticipatie in december 2017 bedraagt 4.1%. Laten we een kaart bouwen die deze snelheid visueel weergeeft.
    7. Klik op de “Classificeren” knop
    8. Selecteer “Handleiding
    9. In de “Breken Waarden”, voer de volgende pauzes in: 0.02, 0.04, 0.06, 0.08
    10. Klik OK. Terug in het laageigenschappenscherm kiest u een kleurverloop die loopt van '8220koud'8221 naar '8220hot'8221. Rode kleuren moeten over het algemeen worden gebruikt om probleemgebieden te symboliseren, dus draai de kleuren indien nodig om (klik met de rechtermuisknop op de kop ' &8220Symbool“).
    11. In de “Label” kolom, label elk symbool als volgt:

    Je bent klaar!


    Lexer.l

    Dit werkt, maar het is traag (2.165 s) op mijn machine, met hetzelfde invoerbestand van miljoenen regels als vermeld in mijn antwoord op de andere vraag.

    Ik heb het op een paar verschillende manieren geprobeerd, maar ik kon geen versie krijgen die sneller was dan de PHP-code in de andere vraag. De logica van de schakelverklaring is aantoonbaar een beetje overdreven slim en slaat alleen de benodigde velden op in de gewenste volgorde, maar de snelheid was ongeveer hetzelfde als de eenvoudige implementatie.

    Als het er toe doet, gebruik ik gcc-versie 10.1 en flex 2.6.4 op een 64-bits Linux-machine.


    Ik denk niet dat je de wildgroei fundamenteel zult kunnen oplossen, omdat je een probleem hebt dat uit veel kleine details bestaat. Deze zullen niet verdwijnen, hoe goed je ze ook organiseert, maar er zijn opties die je helpen ze te organiseren op manieren met minder algoritmische prestatiehits.

    Als je een versie van python met PEP-443 kunt gebruiken, zijn er nog enkele alternatieven, maar ervan uitgaande dat je geen enkele verzendingsondersteuning in je python hebt (ik geloof dat alleen alfa's / bèta's nog zijn vrijgegeven), of je wilt dingen doen handmatig, het is heel goed mogelijk om dit te implementeren met behulp van een dict mapping-type naar functies als alternatief voor de if/elif tree of missing switch statement. De buitenste zou er ongeveer zo uit kunnen zien:

    Ik ben niet helemaal tevreden met de lambda's, ook al heb ik ze gekozen voor een kortere codelengte. De meeste redenen waarom deze code er korter uitziet, is te wijten aan het niet implementeren van de geneste helft van uw oorspronkelijke code. Maar ik denk dat ik de leesbaarheid voor het grootste deel prefereer.

    Ik heb moeite om erachter te komen wat deze functie doet. Ik stopte met concentreren toen ik de else-instructie bereikte en een ander groot if-blok zag. Zulke geneste voorwaarden zijn te veel voor mijn kleine menselijke brein.

    Het probleem is dat deze functie erg laag is - alles wat de functie doet is in detail uitgeschreven. Ik zou zeggen dat ongeveer 90% van de regels code in deze functie ongeveer zijn: hoe de functie doet wat hij doet, niet wat dat doet het echt, ook al is de wat is veel belangrijker dan de hoe.

    Het doel van het verbeteren van code (elke code, niet alleen deze code) zou dus moeten zijn om de belangrijke punten verblindend duidelijk te maken en de saaie, verwarrende details onder het tapijt te vegen. Houd er rekening mee dat je deze code over een jaar misschien opnieuw moet lezen, als je eenmaal helemaal bent vergeten waar het over gaat. Je zult waarschijnlijk ontdekken dat je hersenen ook niet groot genoeg zijn!

    Met dat in gedachten, zou het eenvoudigste wat je zou kunnen doen om deze code te verbeteren, de 'Extract Method' refactoring gebruiken (nou ja, 'Extract Function' in dit geval) op elke arm van je grote if-blok. Een goede vuistregel is dat elke arm van een groot if-blok één regel lang moet zijn. Deze refactoring wordt 'Decompose Conditional' genoemd. Als u uw geëxtraheerde methoden zorgvuldig noemt, zal de functie op het hoogste niveau glashelder zijn in zijn bedoelingen.

    Het is ook een goed idee om isinstance te gebruiken, in plaats van expliciet type in te schakelen, om uw functies subklasse-vriendelijker te maken. Als sommige van de typen die u inschakelt subklassen van elkaar zijn, moet u mogelijk uw elif-instructies opnieuw ordenen om te voorkomen dat het gedrag van de functie verandert. (Ik hoop dat je unit tests hebt!)

    Een kort voorbeeld van hoe extractiemethoden een functie kunnen opschonen:

    Zijn voor de hand liggend wat deze functie nu doet! Als het argument een TypeDecl is, komt het terug op decl.type als het een Union is, dan creëert het een Union-definitie als het een onbekend type is, dan creëert het een andere struct daarvoor, enzovoort. Bovendien kunt u zien wat elke geëxtraheerde functie ook doet - lees gewoon de namen! Dit maakt het gemakkelijker om de code die u zoekt te vinden wanneer u deze moet debuggen.

    Ten slotte is het de moeite waard om erop te wijzen dat als dit soort schakelaar meer dan eens in je programma voorkomt, je mijn persoonlijke favoriete refactoring kunt gebruiken, 'Voorwaardelijk vervangen door polymorfisme'. Dit houdt in feite in dat de herhaalde voorwaardelijke logica wordt verplaatst naar een enkele fabrieksfunctie, die verschillende implementaties van een interface retourneert.


    Bekijk de video: Basic Field Calculator