Seite 1 von 1

@autoproperty

Verfasst: Sonntag 3. Juni 2007, 23:17
von mitsuhiko
Also das ist eher proof-of-concept als für den wirklichen Einsatz gedacht. Was macht es?

Code: Alles auswählen

class Foo(object):

    def __init__(self, initial):
        self.foo = initial

    def _get_foo(self):
        return self._foo

    def _set_foo(self, value):
        self._foo = value

    foo = property(_get_foo, _set_foo, 'The docstring')
    del _get_foo, _set_foo
wird zu

Code: Alles auswählen

class Foo(object):

    def __init__(self, initial):
        self.foo = initial

    @autoproperty
    def foo():
        '''The docstring'''
        def fget(self):
            return self._foo
        def fset(self, value):
            self._foo = value
Code ist hier: http://lucumr.pocoo.org/trac/repos/autoproperty.py

Anmerkungen erwünscht :D

Verfasst: Sonntag 3. Juni 2007, 23:33
von veers
Hm, ich Frage gerade ob das Sinn macht. Daher ob es wirklich einfacher zu lesen/verstehen? Wenn ich mir dann noch ansehe wie hacky die Implementierung ist muss ich sagen dass ich die explizite Definition bevorzuge.

Es ist aber ein schönes Beispiel dafür wie weit man in Python gehen kann.

Re: @autoproperty

Verfasst: Sonntag 3. Juni 2007, 23:37
von gerold
blackbird hat geschrieben:Anmerkungen erwünscht
Hallo blackbird!

Normalerweise vermeide ich Dekoratoren wie die Pest, aber das scheint kein so schlechter Verwendungszweck dafür zu sein. Finde ich wirklich gut. Das kommt den Properties unter Visual Basic .NET sehr nahe. Besonders gefällt mir, dass man nicht zwei oder drei mal einen Docstring schreiben muss. Wie es derzeit ist: einer für den Getter, einer für den Setter und dann noch für das Property.

Nur der Name "@autoproperty" kommt mir noch komisch vor. Ich hätte vielleicht "@propertydef" oder so was ähnliches genommen. Das beginnt mit "property" und zeigt schon nach vier Zeichen auf, für was der Name steht.
Die "auto"-Namen könnte man beim schnellen Durchlesen/Scannen leicht mit Begriffen wie "@autocommit", "@autoexpand", usw. verwechseln.

Wäre schön, wenn so etwas direkt ins Python integriert wäre. :-)

mfg
Gerold
:-)

Verfasst: Montag 4. Juni 2007, 00:09
von BlackJack
Ohne viel Magie und nicht viel länger:

Code: Alles auswählen

class A(object):
    def __init__(self, spam):
        self._spam = spam
    
    @apply
    def spam():
        def fget(self):
            return self._spam
        def fset(self, value):
            self._spam = value
        doc = 'some docs'
        return property(**locals())
Wenn das `apply()` nicht gefällt, kann man ja irgendwo vorher ``autoproperty = apply`` schreiben. :-)

Verfasst: Montag 4. Juni 2007, 08:03
von gerold
BlackJack hat geschrieben:Ohne viel Magie und nicht viel länger
Hallo BlackJack!

Das ist auch nicht schlecht. Der Wermutstropfen ist, dass "apply" seit Version 2.3 "deprecated" ist. Es hat wohl niemand daran gedacht, dass man damit so ein Konstrukt zusammen bringt. Gibt es alternativen zu "apply"?

mfg
Gerold
:-)

Verfasst: Montag 4. Juni 2007, 08:46
von BlackJack
Man kann es sich selber schreiben:

Code: Alles auswählen

def apply_(func, *args, **kwargs):
     return func(*args, **kwargs)
Und dabei dann vielleicht auch gleich einen schöneren Namen geben, der eher nach `property()` klingt.

Verfasst: Montag 4. Juni 2007, 08:57
von mitsuhiko

Code: Alles auswählen

def autoproperty(f):
    return property(doc=f.__doc__, **f())

@autoproperty
def foo():
    """foo doc"""
    def fget(self): return 42
    def fset(self, value): pass
    return locals()
Das geht natürlich auch. Mein Codebeispiel im ersten Post ist auch, wie gesagt, proof-of-concept und nicht ernsthafter Code :-)

Re: @autoproperty

Verfasst: Montag 4. Juni 2007, 13:36
von Y0Gi
gerold hat geschrieben:Besonders gefällt mir, dass man nicht zwei oder drei mal einen Docstring schreiben muss. Wie es derzeit ist: einer für den Getter, einer für den Setter und dann noch für das Property.
Muss man das? Den Docstring bekommt doch `property` als letztes Argument.

Re: @autoproperty

Verfasst: Montag 4. Juni 2007, 14:17
von gerold
Y0Gi hat geschrieben:Muss man das? Den Docstring bekommt doch `property` als letztes Argument.
Hallo Y0Gi!

Nein, das muss man nicht. Aber es kommt schon mal vor, dass sich Getter, Setter und Property-Definition auf mehrere Seiten verteilen. Der Docstring ist in erster Linie **für mich**. Ich möchte einen Code von oben nach unten durchscannen können und anhand der Docstrings oder Kommentare wissen, was sich so tut. Wenn aber der zugehörige Docstring erst eine oder zwei Seiten weiter unten auftaucht, dann bringt er mir nichts mehr.

Der Docstrings in der Property-Definition ist dann nur noch für den Benutzer des Properties interessant, aber nicht mehr für mich. Deshalb haben meine Getter und Setter auch einen Docstring. Auch deshalb, weil manche Getter und Setter (intern) auch ab und zu noch als reine Funktionen angesprochen werden. Z.B. um Standardwerte einer Funktion anzusprechen, auf die man bei der Verwendung von "property" nicht zu kommt.

lg
Gerold
:-)

Verfasst: Dienstag 5. Juni 2007, 16:10
von EyDu
[quote="EyDu"]Also wenn sich hier nicht direkt eine Metaklasse anbietet. Sorry wegen des unkommentierten Codes, aber ist gerade knapp mit der Zeit...

Code: Alles auswählen

class PropMeta(type):
    def __new__(mcls, name, bases, clsdict):
        for name, value in clsdict.iteritems():
            try:
                name = value._property_name
            except AttributeError:
                pass
            else:
                clsdict[name] = property(**value())
                
        return super(PropMeta, mcls).__new__(mcls, name, bases, clsdict)

def propdec(function):
    function._property_name = function.__name__
    return function


class Spam(object):
    __metaclass__ = PropMeta

    def __init__(self, value):
        self.value = value

        print self.aproperty
        self.aproperty = 4
        print self.aproperty
        
    @propdec
    def aproperty():
        def fget(self):
            return self.value**2
        def fset(self, value):
            self.value = value
        doc = "some value"

        return locals()
Der Dekorator ließe sich noch locker um einen property-Namen erweitern, aber da hatte ich jetzt keine Lust zu.

Edit:
Das mein Beispiel funktioniert sieht man ja, aber ich frage mich, ob es sich dafür wirklich lohnt, jedes mal das entsprechende Modul zu importieren, die Metaklasse zu setzen und dann noch die Konflikte mit eventuell anderen benötigten Metaklassen zu lösen.

Verfasst: Dienstag 5. Juni 2007, 17:34
von birkenfeld
Du musst ja nicht jedesmal die Metaklasse importieren und setzen.

Erstelle einfach eine "Basis"-Klasse, z.B.

Code: Alles auswählen

class autoproperty(object):
     __metaclass__ = PropMeta
und lass dann alle deine Objekte von dieser erben.