Hallo,
ich kenne/kannte das Prinzip der nested functions nicht.
Wohl habe ich verstanden wie dies zu programmieren wäre,
nur erschliesst sich mir nicht warum ich das tun sollte.
In Dive into Python wird zwar gesagt, dass nested functions nur aus der Funktion
heraus gestartet werden in welcher diese definiert sind, aber leider
wird nicht erklärt was der Vorteil/Zweck ist.
Kann es sein, dass man damit eine Art "private" Funktion deklarieren will?
Danke
Claudia
Nested Functions
Du paraphrasierst das Buch, darum weiss ich nicht genau, ob die das so sagen - aber so wie *du* das sagst, ist das falsch. Man ruft nested funktionen nicht notwendigerweise nur innerhalb der umgebenden Funktion auf.
Und Anwendungen sind vielfaeltig:
- als kleine Hilfsfunktionen in zB Praedikaten fuer sowas wie filter oder List-comprehensions.
- generell als code-schnipsel die fuer sich funktionieren, aber den globalen oder Klassennamensraum nicht "zumuellen" sollen
- sehr wichtig: als closure, um zB callbacks zu erzeugen, die aber impliziten Zustand haben. ZB fuer Dekoratoren aller Arten:
Und so weiter und so fort.
Und Anwendungen sind vielfaeltig:
- als kleine Hilfsfunktionen in zB Praedikaten fuer sowas wie filter oder List-comprehensions.
- generell als code-schnipsel die fuer sich funktionieren, aber den globalen oder Klassennamensraum nicht "zumuellen" sollen
- sehr wichtig: als closure, um zB callbacks zu erzeugen, die aber impliziten Zustand haben. ZB fuer Dekoratoren aller Arten:
Code: Alles auswählen
def synchronized(f):
def _w(self, *args, **kwargs):
with self.lock:
return f(self, *args, **kwargs)
return _w
class Foo(object):
def __init__(self):
self.lock = threading.Lock()
@synchronized
def mach_watt(self):
print "boo!"
- pillmuncher
- User
- Beiträge: 1484
- Registriert: Samstag 21. März 2009, 22:59
- Wohnort: Pfaffenwinkel
Das Beispiel von deets ist eine Inkarnation hiervon: http://de.wikipedia.org/wiki/Closure.
Hier ein anderes Beispiel, bei dem allerdings die innere Funktion nicht außerhalb ihres umgebenden Kontexts verwendet wird:Das Ergebnis müsste dann ungefähr so aussehen:Die Reihenfolge wird möglicherweise variieren.
Hier ein anderes Beispiel, bei dem allerdings die innere Funktion nicht außerhalb ihres umgebenden Kontexts verwendet wird:
Code: Alles auswählen
from collections import defaultdict
def connected_components(edges):
neighbors = defaultdict(set)
for a, b in edges:
neighbors[a].add(b)
neighbors[b].add(a)
visited = set()
def component(node): # <-- hier wird eine Funktion definiert, die Zugriff auf den sie umgebenden
stack = [node] # Kontext hat, die aber nicht außerhalb dieses Kontexts verwendet wird.
while stack:
node = stack.pop()
visited.add(node)
yield node
stack.extend(n for n in neighbors[node] if n not in visited)
for node in neighbors:
if node not in visited:
yield set(component(node)) # <-- hier wird die Funktion verwendet.
some_graph = [(1, 2), (1, 3), (2, 7), (4, 5), (4, 6), (5, 5), (6, 5)]
print list(connected_components(some_graph))
Code: Alles auswählen
[set([1, 2, 3, 7]), set([4, 5, 6])]
In specifications, Murphy's Law supersedes Ohm's.
@deets, @pillmuncher,
vielen Dank für Eure Hilfe.
Kann man sagen, dass das primäre Ziel von nested functions der ist, diese im lokalen Kontext zu halten?
@deets - Wird bei deinem Beispiel nicht erst hier
die Funktion aufgerufen?
Wenn ja, dann würde diese ja wieder erst in der sie umgebenden Funktion synchronized aufgerufen, oder?
Danke
Claudia
vielen Dank für Eure Hilfe.
Kann man sagen, dass das primäre Ziel von nested functions der ist, diese im lokalen Kontext zu halten?
@deets - Wird bei deinem Beispiel nicht erst hier
Code: Alles auswählen
return _w
Wenn ja, dann würde diese ja wieder erst in der sie umgebenden Funktion synchronized aufgerufen, oder?
Danke
Claudia
- pillmuncher
- User
- Beiträge: 1484
- Registriert: Samstag 21. März 2009, 22:59
- Wohnort: Pfaffenwinkel
@myxin: Vielleicht wird es dadurch klarer:Ergebnis:
Gruß,
Mick.
Code: Alles auswählen
def add_n(n):
def adder(m):
print 'nachher'
return m + n
return adder
f_5 = add_n(5)
print 'vorher'
print f_5(2)
Code: Alles auswählen
vorher
nachher
7
Mick.
In specifications, Murphy's Law supersedes Ohm's.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Jein. f_5 ist eine Funktion. Eine Funktion vom Typ "Funktion", weil in Python haben Funktionen nun mal so einen Typ. Es ist an sich die Funktion ``adder`` die den Namen ``m`` als Parameter hat und den Namen ``n`` aus dem Namensraum der Funktion nimmt in der sie definiert wurde (``add_n``).myxin hat geschrieben:ahhh - heisst, f_5 ist jetzt eine Funktion vom Typ addr, oder?
Da mag auf den ersten Blick ein relativ sinnloses Feature zu sein, aber es gibt einen Programmierstil wo sowas häufig zur Anwendung kommt. Mal ein Beispiel, du willst eine Liste sortieren:
Code: Alles auswählen
collection = [(2, 3), (4, 2), (4, 1), (5, 5)]
sorted(collection)
# [(2, 3), (4, 1), (4, 2), (5, 5)]
Code: Alles auswählen
def second(item):
return item[1]
sorted(collection, key=second)
# [(4, 1), (4, 2), (2, 3), (5, 5)]
Code: Alles auswählen
def get_nth_item(num):
def inner(item):
return item[num]
return inner
Code: Alles auswählen
sorted(collection, key=get_nth_item(1))
# [(4, 1), (4, 2), (2, 3), (5, 5)]
Die nächste Vereinfachung wäre übrigens festzustellen dass es so eine Funktion in der Stdlib bereits gibt:
Code: Alles auswählen
from operator import itemgetter
sorted(collection, key=itemgetter(1))
# [(4, 1), (4, 2), (2, 3), (5, 5)]
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
@Leonidas
vielen Dank für die Erklärung und das Beispiel.
Ich will nicht behaupten, dass ich das mit den nested functions jetzt 100%ig verstanden habe,
aber ich denke ich habe eine gute Idee davon bekommen.
Ich denke ich muss da ein bisschen mit spielen um dies zu vertiefen.
Danke
Claudia
vielen Dank für die Erklärung und das Beispiel.
Ich will nicht behaupten, dass ich das mit den nested functions jetzt 100%ig verstanden habe,
aber ich denke ich habe eine gute Idee davon bekommen.
Ich denke ich muss da ein bisschen mit spielen um dies zu vertiefen.
Danke
Claudia