måndag 14 maj 2007

Lektion 4: use the force, Luke

Allt Sker Runtime.
Allt Är Objekt.

Nåväl. Nästan. Och det gör att sakernas tillstånd blir ljuva för oss programmerare. Det inbyggda nyckelordet "import" funkar ungefär som en runtime-variant av #include i C. Skriv:

>>> import os
>>> os.listdir("C:\\")
['boot.ini', 'Bootfont.bin', 'C_DILLA', 'Documents and Settings', 'NTDETECT.COM', 'ntldr', 'pagefile.sys', 'Program', 'RECYCLER', 'RnD', 'System Volume Information', 'WINDOWS']

Mja. Den koden var enklare i Python än C... Det följande fattar du dock inget av än, men
det visar på en viktig detalj:

>>> m = __import__("os"); getattr(m, dir(m)[74])("C:\\")
['boot.ini', 'Bootfont.bin', 'C_DILLA', 'Documents and Settings', 'NTDETECT.COM', 'ntldr', 'pagefile.sys', 'Program', 'RECYCLER', 'RnD', 'System Volume Information', 'WINDOWS']

Nämligen att det går att göra saker nästan hur som helst i Python. Vid utvecklingen av Python har man ett måtto: "vi ska försöka att få folk att göra rätt, men om de vill så ska de tamejfan få skriva vilken fungerande griskod som helst".

Och för att åstadkomma diverse runtimetricks så finns gott om inbyggda funktioner till vår hjälp. Du har redan testat på help(). Här ett axplock:

  • import - ungefär som #include.
  • print - ungefär som printf().
  • help() - sammanställer dokumentation rekursivt för ett objekt.
  • dir() - listar medlemmar i ett objekt.
  • hasattr() - kollar om ett objekt har en medlem med ett visst namn.
  • callable() - returnerar True/False beroende på om ett objekt går att anropa eller ej.
  • file() - filklass.
  • open() - filöppningsfunktion.
  • filter() - funktionell filtrering.
  • map() - funktionell mappning.
  • reduce() - funktionell reducering.
Så för att testa lite introspection så får du skriva lite kod som jag har snott från Mark Pilgrim:

>>> def info(object, spacing=10):
         methodList = [method for method in dir(object) if callable(getattr(object, method))]
         processFunc = lambda s: " ".join(s.split())
         print "\n".join(["%s %s" % (method.ljust(spacing), processFunc(str(getattr(object, method).__doc__))) for method in methodList])

>>> class sunkKlassen:
         def a(self):
                 """Min dokumenterade funktion...
                 Jajjemen.
                 Du.

                 Missa ej min dokumentation,
                 annars blir det att smaka min menstruation..."""
                 pass
         def b(self, x):
                 "Men finare dokumenterat i b()!"
                 pass

>>> a = sunkKlassen()
>>> info(a)
a          Min dokumenterade funktion... Jajjemen. Du. Missa ej min dokumentation, annars blir det att smaka min menstruation...
b          Men finare dokumenterat i b()!

Funktionen info() gör följande

  1. plockar ut alla medlemmar som är anropningsbara och lägger i variabeln "methodList".
  2. Sedan skapar den en funktion, "processFunc" som ersätter alla whitespaces med ett enda space.
  3. Sist skapar den en lista som består av metodnamnet och dess dokumentation, och så jämkar den ihop alla dessa med en linefeed ("\n").

Det ser svårare ut än vad det är; när du väl är van så är Pythonkod lättläst.

Detta var det svåraste kapitlet, och antagligen fattar du inget nu. Misströsta ej, det kommer när du experimenterat lite.

Nästa kapitel är kort och enkelt och mycket, mycket vackert.

Inga kommentarer: