ubuntuusers.de

[Python-Skript] deb-cleaner

Status: Gelöst | Ubuntu-Version: Nicht spezifiziert
Antworten |

MrKanister

(Themenstarter)

Anmeldungsdatum:
13. Oktober 2007

Beiträge: 2105

audax hat geschrieben:

    if not isinstance(paths, list):
        raise TypeError("list object expected, got %s." % type(paths))


Den Teil kann man sich sparen.

(os.path.abspath(path) for path in paths)
imap(os.path.abspath, paths)


Welches von beiden ist vllt auch ein wenig Geschmackssache, ich persönlich mag map

Der instance-Test ist schon wichtig:

>>> paths = "/Pfad/Zum/Verzeichnis"
>>> for path in (os.path.abspath(path) for path in paths):
...     print path
... 
/
/home/martin/P
/home/martin/f
/home/martin/a
/home/martin/d
/
/home/martin/Z
/home/martin/u
/home/martin/m
/
/home/martin/V
/home/martin/e
/home/martin/r
/home/martin/z
/home/martin/e
/home/martin/i
/home/martin/c
/home/martin/h
/home/martin/n
/home/martin/i
/home/martin/s
>>> 


😉

audax hat geschrieben:

Außerdem solltest du mal die Klamern um die yield, returns und prints entfernen: Noch sind wir nicht bei Py3k, und auch dann machts der Konverter 2to3.py schon selbst 😉

Da die Klammern nicht fehlerhaft sind, ist es doch von Vorteil, wenn ich sie jetzt schon setze...so gewöhne ich mich direkt dran 😀

Mir fällt gerade auch auf, dass man selbst mit "apt.VersionCompare" gewaltig auf die Nase fallen kann:

>>> from apt import VersionCompare
>>> VersionCompare("1.4a3", "1.4")


Und das obwohl eine Alpha-Version definitiv nicht aktueller ist, als die finale Version 😕

Eventuell wäre es besser auf "pkg_resources.parse_version" um zu steigen:

>>> from pkg_resources import parse_version
>>> parse_version("1.4a3") > parse_version("1.4")
False


Ich glaube ich werde damit ein wenig rumspielen... ☺

Gruß Martin

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

Der instance Test ist aber unnötig, weil er das Programm unflexibler macht und keinen Fehler, den man nicht sowieso durchs Testen sieht, verhindert.

Und das mit den Klammern ist trotzdem blöd, weil 2to3.py nochmal Klammern darum setzt. und ein yield( (foo) ) sieht doof aus.

parse_version ist übrigens viel besser und fixer, weil du die Funktion einfach fürs key-Argument nutzen kannst.

MrKanister

(Themenstarter)

Anmeldungsdatum:
13. Oktober 2007

Beiträge: 2105

audax hat geschrieben:

Der instance Test ist aber unnötig, weil er das Programm unflexibler macht und keinen Fehler, den man nicht sowieso durchs Testen sieht, verhindert.

Ups...du hast Recht...ich seh grad, dass ich mit "args" ja sowieso eine Liste übergebe 😳

audax hat geschrieben:

Und das mit den Klammern ist trotzdem blöd, weil 2to3.py nochmal Klammern darum setzt. und ein yield( (foo) ) sieht doof aus.

OK, das wusste ich nicht.

audax hat geschrieben:

parse_version ist übrigens viel besser und fixer, weil du die Funktion einfach fürs key-Argument nutzen kannst.

Was mich hier ein wenig wundert ist, dass ich die Key-Funktion so schreiben muss:

lambda obj: parse_version(obj[1])


Aber folgendes müsste doch auch funktionieren:

parse_version(itemgetter(1))


Ich erhalte allerdings

Traceback (most recent call last):
  File "./debcleaner", line 115, in <module>
    main()
  File "./debcleaner", line 94, in main
    for package in packages2delete(directory, options.num):
  File "./debcleaner", line 34, in packages2delete
    compare_by_version = parse_version(itemgetter(1))
  File "/usr/lib/python2.5/site-packages/pkg_resources.py", line 1877, in parse_version
    for part in _parse_version_parts(s.lower()):
AttributeError: 'operator.itemgetter' object has no attribute 'lower'


Eigentlich müsste doch die Funktion "itemgetter" zuerst ausgewertet werden und das 1. Element der Liste zurückgeben, welches dann von "parse_version" umgewandelt wird!?

Gruß Martin

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

Mr. Kanister hat geschrieben:

Was mich hier ein wenig wundert ist, dass ich die Key-Funktion so schreiben muss:

lambda obj: parse_version(obj[1])


Aber folgendes müsste doch auch funktionieren:

parse_version(itemgetter(1))


Ich erhalte allerdings

Traceback (most recent call last):
  File "./debcleaner", line 115, in <module>
    main()
  File "./debcleaner", line 94, in main
    for package in packages2delete(directory, options.num):
  File "./debcleaner", line 34, in packages2delete
    compare_by_version = parse_version(itemgetter(1))
  File "/usr/lib/python2.5/site-packages/pkg_resources.py", line 1877, in parse_version
    for part in _parse_version_parts(s.lower()):
AttributeError: 'operator.itemgetter' object has no attribute 'lower'


Eigentlich müsste doch die Funktion "itemgetter" zuerst ausgewertet werden und das 1. Element der Liste zurückgeben, welches dann von "parse_version" umgewandelt wird!?

itemgetter(1) erzeugt eine Funktion, die du gleich an parse_version übergibst. Natürlich kann parse_version nichts mit einer Funktion anfangen, ist ja kein String.
Du musst also parse_version(itemgetter(1)(foo)) ausführen, oder eben parse_version(foo[1]) 😉

Alternativ:

imap(itemgetter(1,0,2), sorted(imap(itemgetter(1,0,2), key=parse_version)))

Was in Python irgendwie fehlt ist Composing 😀
Damit sähe das viel hübscher aus:

sorted(foo, key=parse_version . itemgetter(1))


Aber naja, man kann nicht alles haben.

Hello_World

Anmeldungsdatum:
13. Juni 2006

Beiträge: 3620

Funktionskomposition kann man sich doch trivial selber bauen:

def composit(*functions):
        if functions:
                return lambda x: functions[0](composit(*functions[1:])(x))
        else:
                return lambda x: x


Bei dieser Implementierung ist composit() gleich der Identität. Möglich, dass das mathematisch nicht korrekt ist, ich kenne die genaue Definition nicht.

MrKanister

(Themenstarter)

Anmeldungsdatum:
13. Oktober 2007

Beiträge: 2105

Es gibt sogar ein eigenes Modul dafür: http://oakwinter.com/code/functional/

Habs hier gefunden: http://docs.python.org/dev/3.0/howto/functional.html#the-functional-module

itemgetter(1) erzeugt eine Funktion, die du gleich an parse_version übergibst. Natürlich kann parse_version nichts mit einer Funktion anfangen, ist ja kein String.
Du musst also parse_version(itemgetter(1)(foo)) ausführen, oder eben parse_version(foo[1]) 😉

Ah...ok...Danke ☺

Gruß Martin

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

Klar, kann man:

def compose(*funcs):
    def comp(f, g):
        return lambda *args: f(g(*args))
    return reduce(comp, funcs)

Aber ne eigene Syntax dafür fände ich schon knorke, oder zumindest compose() in functools...
Aber da haben die was gegen und meinen, dass lambda reiche.

Antworten |