Pythonin and-or-lausekkeet

Thursday, November 12th 2009 at 23:20 in Technology, Python

[UPDATE: Katso kommenteista parempi tapa tehdä tämä.]

Tämä on uusi lempilausekkeeni Pythonissa:

result = condition and option1 or option2
# Esim:
name = user.is_authenticated() and user.username or u'anonymous'

Tuo vastaa täydellisesti C:stä ja Javasta tuttua ?:-ehtolauseketta:

name = user.is_authenticated() ? user.username : "anonymous";

Nyt ei tarvitse enää pitkiä if-else-lauseita, kun Pythonin boolean-logiikka hoitaa homman noin.

13 Comments
Heikki Hallamaa 13.11.2009 04:52:33

Tuossa tavassa on ongelmansa, jotka saattavat ilmentyä jännissä paikoissa yllättäen. Vrt:

True and 1 or 2 1 True and 0 or 2 2

Sen sijaan python on versiosta 2.5 lähtien käyttänyt omaa syntaksiaan ehtolausekkeille: x = true_value if condition else false_value

Kennu 13.11.2009 06:39:26

Hyvä tietää! Siirrynkin käyttämään tuota.

Bro 16.11.2009 19:04:03

PHP:ssahan on tuo sama ominaisuus ja se on kyllä omiaan obfuskoimaan koodia semmoiseksi ettei sitä pysty vaan lukaisemaan läpi, hate.

Kennu 18.11.2009 13:37:57

Bro: PHP:ssä on se ongelma, että koodia tulee kauhean paljon ja sen parsiminen päässä on vaikeaa. Pythonissa saa usein aikaan konstrukteja, jotka ovat vain muutaman rivin mittaisia ja rakenteeltaan aika vakiomuotoisia, joten niihin tottuu nopeasti. Minusta pienimuotoinen kryptisyys on hyväksyttävää, jos lopputuloksena on kuitenkin kokonaisuutena merkittävästi yksinkertaisempi koodi.

Tommi F. 18.11.2009 16:36:59

Ternary operator (joka on siis PHP:n lisäksi tuttu melkein kaikista C-johdannaisista kielistä) on kyllä kaksiteräinen miekka. Sillä saa ihan älyttömän tehokasta ja kompaktia koodia, kunhan sen kanssa pitää housut jalassa, mutta sillä saa myös vietyä muuten siistin koodin PERL-linjakohinan tasolle.

PHP:lla on älyttömästi ansiotaan paskempi maine. Se on vähän samalla tavalla hankala kieli, kuin JavaScript: huonoissa käsissä paskinta ikinä, osaavissa käsissä älyttömän toimiva ympäristö.

PHP:n huonolla maineella on tasan yksi oikea syy: maailma on täynnä paskoja PHP-koodaajia.

Kennu 18.11.2009 17:33:50

Väittäisin kyllä, että PHP:ssä on ihan oikeasti isoja puutteita kielenä. Niitä on ehkä vähän paikkailtu nyt ihan uusimmissa versioissa, mutta sekin vie pitkän aikaa, ennen kuin closuret ja nimettömät funktiot ja vastaavat uudet ominaisuudet otetaan esim. käyttöön frameworkeissa, joiden varaan sovellukset kuitenkin rakentuu.

Sitten on sellaisia asioita, joita on vaikea paikata, kuten array-syntaksin kauhea verboosius. Datan käsittely PHP:ssä kuitenkin perustuu hyvin pitkälti assosiatiivisten arrayden ja niitä käpistelevien funktioiden varaan.Vrt. PHP:ssä joku array_slice(array(array('eka' => array(1, 2, 3)), array('toka' => array(4, 5, 6))), 1, 1) versus Pythonin [{'eka': [1, 2, 3]}, {'toka': [4, 5, 6]}][1:2].

JavaScript taas on tosiaan ollut jo vuosien ajan tosi kehittynyt kieli, jolla voi tehdä vaikka mitä jos osaa. Mulla on suuri respekti sitä kohtaan. jQuery sai näkemään valon sen suhteen.

Tommi Forsström 19.11.2009 20:59:45

Verbositeetti ei missään tapauksessa ole mun silmissä laadullisesti arvottava tekijä. Minua enemmänkin ärsyttää Pythonissa ja Rubyssä yritys yksinkertaistaa juttua, joka vain olisi selkeämpi kuvata pidemmällä konstruktiolla. PHP:ssäkin koodin formatointi tekee todella ihmeitä sen sisällön hahmottamiselle. Juuri tästä syystä paskat PHP-koodaajat ovat suurin syy sen huonoon maineeseen, koska verboosi kieli + huono formatointi = linjakohinaa. Mutta minun mielestäni NumberOfEventsPerYear on oikeasti ihan älyttömästi parempi muuttujan nimi kuin numEveYear. Sitä varten meillä on kehittyneet IDEt ja niissä Intellisenset.

PHP:n puutteet ovat kuitenkin aika marginaalisia ottaen huomioon mikä sen tehtävä ja rooli on.

Javascript on jo todella pitkään ollut älyttömän hyvä kieli. Platat (= selaimet), joilla sitä käytetään ovat vaan olleet mitä sattuu. Kielen suurin vahvuus on kuitenkin sen suurin heikkous: joustavuus. Kun kaiken voi monkeypatchata, mitään ei tarvitse tyypittää ja oikeastaan mitä tahansa voi tehdä, voi olla varma, että maailman pellepelottomat ja sunnuntaikoodaajat odottavat sormet syyhyten päästä tuottamaan DailyWTF:lle materiaalia.

Jos mä aloittaisin koodaamisen tänään, mä keskittyisin 99%:sti vain Javascriptin opetteluun. Coding Horror -blogin Jeff Atwoodin leikkimielinen "Atwood's Law" pitää aika tarkalleen paikkansa:

"Any application that can be written in JavaScript, will eventually be written in JavaScript"

Kennu 19.11.2009 21:16:33

Olemme sitten eri linjoilla verbositeetin suhteen. Verbositeetti on nimittäin käytännössä sama asia kuin DRY-periaatteen rikkominen, eli turhaan toistetaan samoja asioita ja lisätään koodiin ylimääräistä volyymiä ja ylimääräisiä rivejä, jolloin enemmän asioita voi myös mennä rikki ja bugata.

Tommi Forsström 19.11.2009 22:54:07

Eihän DRY:ssä ole missään tapauksessa kyse ylimääräisten merkkien karsimisesta! Samantien voisi palata PERL-pelleilyyn tai koodata kaikki stringien käsittelyt regexpeillä. Ei koodin bittimäärän minimointi ole millään mielellä järkevä tavoite, ainoastaan koodissa tehtävien operaatioiden määrän minimointi!

Sitä varten IDEt ja työkalut ovat kehittyneet ihan tolkutonta tahtia, että koodin määrällä ei olisi mitään väliä, vaan pääpaino voisi olla luettavassa koodissa. Jos merkkien määrää yritetään kaikin voimin himmata, jotta päästään ultrakompaktiin koodiin, jossain kohtaa lentää luettavuus suoraan pihalle. Siitä seuraa tosiaan vain PERL all over again. Eikä sitä halua edes pahimmalle viholliselleen.

Kennu 19.11.2009 23:00:44

No okei, ehkä kärjistin liikaa DRY == lyhyt koodi, mutta arvostan molempia. Erityisesti koodirivien suuri määrä ärsyttää. Vrt. PHP:

$curl = curl_init(); curl_setopt($curl, CURLOPT_URL, 'http://www.google.com'); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $data = curl_exec($curl); curl_close($curl);

vs. Pythonissa

data = urllib2.urlopen('http://ww.google.com').read()

Eli turha ylimääräinen scheisse pois, se on minun viestini. Joskus kyse on DRY:stä, joskus muuten vaan tarpeettoman monimutkaisuuden karsimisesta. Itse heitän mieluiten IDEt ja IntelliSenset ja muut bloatingenerointivälineet romukoppaan ja editoin vimillä lyhyttä, yksinkertaista siistiä koodia. (GUI-suunnittelu on sitten erikseen.)

Tommi Forsström 19.11.2009 23:06:11

Hehe, kiitos että validoit pointtini PHP:n maineesta ja huonoista PHP-koodaajista ;D

$data = file_get_contents("http://ww.google.com")

PHP:ssäkin on toki se ongelma, että saman jutun voi tehdä useammalla tavalla.

Tommi Forsström 19.11.2009 23:17:04

...mutta se mitä tässä nyt kierrellään eniten on fakta, että Python ja vertaisryhmänsä aktiivisesti ohjaavat tiiviin ja kuvailevan koodin kirjoittamiseen, siinä missä JS ja PHP jopa työntävät älyttömän kankean ja vaikeaselkoisen koodin kirjoittamiseen. Siksi niissä pitääkin olla erikoisosaamista ja kurinalaisuutta, että koodi pysyy luettavana ja yksinkertaisena.

ps. Yksi PHP-skenen "helmasynti", jota en yksinkertaisesti osaa tajuta, on <?php-alkutägin preferointi <?-alkutägin sijaan. Tuo täysin turha "php" tuolla alussa on just ne kolme tavua, joita mä en ainakaan kaipaa.

Kennu 19.11.2009 23:26:53

No niin, tämä menee nyt ihan kissa-hiiri-leikiksi keksiä PHP:n ongelmallisia koodirakenteita :-) Itse olen joskus törmännyt ongelmiin file_get_contentsin kanssa ja käyttänyt suosiolla aina CURL-kirjastoa, mutta myönnettäköön, että PHP:stä löytyy valtava määrä tuollaisia lyhyitä apufunktioita tietyn asian tekemiseen kätevästi, ja yksi hyvän kooderin merkki on tuntea ne kaikki.

Vaatisi melkein pitemmän blogikirjoituksen käsitellä niitä etuja, joita Pythonissa esimerkiksi meta classit, keyword-argumentit, list comprehensionit ja muut vastaavat kielelliset featuret tuo PHP:hen nähden, ja joiden avulla koodista saa paljon tiiviimpää. Nämä tässä ketjussa heittelemäni esimerkit eivät ole vielä liittyneet niihin mitenkään.


You can use Markdown to format your comment:

  • > quoted text
  • *italic* text
  • **bold** text
  • `code block` (multi-line is ok, whitespace is preserved)
  • [link text](http://www.google.com "link title")

Separate paragraphs in your text with two newlines