Pyquery 'each()' Wertübergabe

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Thyrix
User
Beiträge: 13
Registriert: Freitag 6. August 2010, 14:25

Hallo zusammen,

ich versuche gerade in einem Skript einen Zähler von außerhalb an eine von 'each()' aufgerufene Funktion zu übergeben.
Ich poste einfach mal kurz eine vereinfachte Form des Codes:

Code: Alles auswählen

def func(x):    
     global i
     
     
    x.prepend('<a title="bla" href ="link"' + str(i) + '></a>')



     i = i + 1
     return lambda x: x


i = 0
d('#content p').each(func)

Grob gesagt: Die letzte Zeile ruft für jedes '<p>' im Pyquery Objekt 'd' die Funktion 'func' auf.
Das große Problem ist, dass das Python-'global' nur Schreiberechte innerhalb der Funktion gewährt (==> 'i = i + 1' funktioniert), ich aber dringend auch Leserechte benötige (für das, was hier als 'print i' dargestellt ist).

Meine Fragen also:

1. Gibt es eine Möglichkeit, die Variable 'i' noch "globaler" zu machen oder irgendetwas in der Art zu erzwingen, damit das funktioniert?

2. Von 'each()' wird der entsprechende Inhalt aus 'd' direkt an 'x' in 'func' übergeben. Weitere Parameter beim Aufruf werden vom Programm nicht verstanden und geben eine Fehlermeldung. Besteht eine Möglichkeit, 'i' irgendwie bei der Übergabe von dem, was zu 'x' wird, in der Struktur des übergebenen Parameters unterzubringen?
Oder überhaupt auf das, was da übergeben wird, zuzugreifen / weitere Parameter zu übergeben?


Viele Grüße und besten Dank schonmal,

Thyrix
Zuletzt geändert von Thyrix am Freitag 6. August 2010, 15:54, insgesamt 1-mal geändert.
BlackJack

@Thyrix: Grundsätzlich verstehe ich das Problem nicht, denn ``print i`` sollte problemlos auf das Modulglobale `i` zugreifen können. Wenn Du etwas vereinfachtes zeigst, solltest Du immer sicherstellen, dass das dann immer noch das Problem aufweist, welches Du lösen willst.

Das `i` in der ``lambda``-Funktion würde ich in etwas anderes umbenennen, damit niemand beim Lesen durcheinanderkommt und das `i` dort mit den anderen `i`\s verwechselt. Oder bist Du da gerade selbst ein wenig verwirrt!?

Ad 1: Du möchtest das `i` eigentlich auch nicht "noch globaler" machen, sondern im Gegenteil viel lokaler. Entweder über eine Klasse oder ein Closure.

Ad 2: Aus einer Funktion, die mehrere Argumente entgegennimmt, eine zu machen die weniger entgegennimmt, indem welche an feste Werte gebunden werden, geht mit `functools.partial()`.
Thyrix
User
Beiträge: 13
Registriert: Freitag 6. August 2010, 14:25

Danke, auf functools bin ich nicht gekommen, probiere ich aus :)

Hmm ich habs natürlich so wies da steht vorher getestet,
und zu dem print i sagt er mir das gleiche, wie wenn ich versuche, i im nicht vereinfachten code zu lesen, nämlich:

Code: Alles auswählen

NameError: global name 'i' is not defined
Ich ändere das oben trotzdem schnell.
BlackJack

@Thyrix: Das Beispiel ist dadurch nicht sehr viel besser geworden. Die Zuweisung an `x` in `func()` ist sinnfrei weil `x` danach nie wieder verwendet wird. Und die ``lambda``-Funktion verwendet jetzt verwirrenderweise auch ein (anderes) `x`. Das ist einfach die Identitätsfunktion die Du dort zurückgibst. Vielleicht sollte die ``lambda``-Funktion *kein* Argument haben!? Denn *dann* würde beim Aufruf der ``lambda``-Funktion das lokale `x` von `func()` zurückgegeben werden.

Edit: Ich habe mal ein wenig die Kristallkugek geputzt. Kann es sein, dass Du so etwas suchst!? (Untegestet)

Code: Alles auswählen

from itertools import count


def make_link_prepender(link_template='link%d', start_number=1):
    counter = count(start_number - 1)
    def prepend_link(item):
        item.prepend('<a title="bla" href="%s"></a>'
                     % (link_template % counter.next()))
    return prepend_link

# ...

document('#content p').each(make_link_prepender())
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Das hier gibt wie erwartet 3 aus:

Code: Alles auswählen

def f():
    global i
    i += 1

i = 0
f(); f(); f()
print(i)
Stefan
Thyrix
User
Beiträge: 13
Registriert: Freitag 6. August 2010, 14:25

@ Blackjack:
Danke ich versuch mal das Teil aus itertools, functools partial war doch nicht wirklich was ich gesucht hatte.
Ähhhm ja vergessen wir das Beispiel einfach mal, Sma hats ja auch falsch verstanden.
Das Lambda funktioniert eigentlich so ganz knorke, ohne Argumente gibts nen Fehler. Aber naja worum es geht ist ja:

Ich brauche einfach nen Zähler innerhalb der Funktion, auf den ich in der Funktion Lese-Zugriff hab.

Werd das wie gesagt jetzt mal testen, gleich mehr dazu.


------------------------------------------------------------------------

Super, hat damit geklappt, danke für deine Bemühungen :)

Viele Grüße,

Thyrix
Antworten