get/set/del Methoden und Property Generator

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Benutzeravatar
name
User
Beiträge: 254
Registriert: Dienstag 5. September 2006, 16:35
Wohnort: Wien
Kontaktdaten:

Dienstag 30. Januar 2007, 16:47

Hallo!
Mir was gestern ein bisschen langweilig und hab ein Programm das mir automatisch get, set und del Methoden und dazugehoerige Properties generiert, z.B.

Code: Alles auswählen

class Game(object):
    def __init__(self, id, serverip=None):
        stdport = '28940'
        self._id = id #P
        self._players = [] #P
        self._Field = Field(self.sock) #P
        self._netPlayer = False #P
    def test(self):
        self._a = "hallo" #P
Das #P bedeutet das mein Programm die Variable parst, einen getter einen setter einen deller und ein dazugehoeriges Property erstellt.
Daraus wird:

Code: Alles auswählen

# Generated code starting.

    def set_id(self, value):
        self._id = value
    def get_id(self):
        return self._id
    def del_id(self):
        del self._id

    def set_players(self, value):
        self._players = value
    def get_players(self):
        return self._players
    def del_players(self):
        del self._players

    def set_Field(self, value):
        self._Field = value
    def get_Field(self):
        return self._Field
    def del_Field(self):
        del self._Field

    def set_netPlayer(self, value):
        self._netPlayer = value
    def get_netPlayer(self):
        return self._netPlayer
    def del_netPlayer(self):
        del self._netPlayer

    def set_a(self, value):
        self._a = value
    def get_a(self):
        return self._a
    def del_a(self):
        del self._a

    id = property(get_id, set_id, del_id)
    players = property(get_players, set_players, del_players)
    Field = property(get_Field, set_Field, del_Field)
    netPlayer = property(get_netPlayer, set_netPlayer, del_netPlayer)
    a = property(get_a, set_a, del_a)

#Generated code ends.
Natuerlich muss man die methoden neu schreiben, trotzdem erspart es ihm ein bisschen Zeit, finde ich.
Die Einschraenkungen sind das das FILE eine Datei sein muss die nur eine Klasse enhaelt, das werde ich aber auch noch einbaun, das das anders geht...

Hier das Programm:

Code: Alles auswählen

import sys
setters = list()
getters = list()
properties = list()
dellers = list()
towrite = str()
def getamount(string):
    i = 0
    count = 0
    while(i < len(string)):
        if(string[i] == " "):
            count+=1
        else:
            return count
        i+=1
def getTabsize(file):
    source = open ( file )
    source = source.readlines()
    i = 0
    while(i < len(source)):
        if source[i].startswith("\t"):
            return "\t"
        if("if" in source[i] or "while" in source[i] or "else" in source[i] or "class" in source[i] or "def" in source[i] and  not getamount(source[i]) == getamount(source[i+1])):
            tabsize=getamount(source[i+1])-getamount(source[i])
            return tabsize
        i+=1
def getTabs(filename):
    global tab
    global newline
    tabs = getTabsize(filename)
    if tabs != "\t":
        tabs = " "*tabs
    newlines = "\n"
    tab = tabs
    newline = newlines
def getParseVars(filename):
    global filenames
    filenames = filename
    returnl = list()
    fi = open ( filename ).readlines()
    for line in fi:
        if "self" in line and "#P" in line:
            if line.endswith("\n"):
                line = line[:-1]
            splitline = line.split("=")
            for elem in splitline:
                if "self" in elem and not "#P" in elem and elem == splitline[0] \
                and "_" in elem:
                    returnl.append(elem.strip())
    return returnl
def getSetter(var):
    vatsettername = getVarName(var)
    setters.append( "%sdef set_%s(self, value):%s\
    %s%s%s = value\n" % (tab,vatsettername, newline, tab, tab, var) )
def getGetter(var):
    print 'getter'
    varsettername = getVarName(var)
    getters.append( "%sdef get_%s(self):%s\
    %s%sreturn %s%s" %
                    (tab,varsettername,newline,tab,tab,var,newline) )
def getDeller(var):
    print 'getter'
    varsettername = getVarName(var)
    dellers.append( "%sdef del_%s(self):%s%s%sdel %s\n" % (tab,varsettername, newline, tab, tab, var) )
def getProperty(var):
    varsettername = getVarName(var)
    properties.append("%s%s = property(get_%s, set_%s, del_%s)%s" %
                    (tab,varsettername,varsettername,varsettername,varsettername,newline))
def getVarName(var):
    var = var.replace("self._","")
    return var
def createLists(filename):
    global varnames
    varnames = list()
    wrote = list()
    for var in getParseVars(filename):
        if not var in wrote:
            varnames.append(var)
            getSetter(var)
            getGetter(var)
            getProperty(var)
            getDeller(var)
            wrote.append(var)
def writeCode(filename):
    towrite = "\n# Generated code starting.\n\n"
    for i in range(len(getters)):
        towrite+=setters[i]
        towrite+=getters[i]
        if dellers:
            towrite+=dellers[i]
        towrite+="\n"
    for property in properties:
        towrite+=property
    towrite+="\n#Generated code ends.\n"
    print towrite
    fl = open ( filenames, "a")
    fl.write(towrite)
    fl.close()
def printVars():
        for var in varnames:
            print var
def help():
    print "USAGE: %s [FILE] [OUTPUTFILE]" % sys.argv[0]
    print "If no OUTPUTFILE is defined, the output is appended to FILE"
def do(filename ,writefilename=None):
    if not writefilename:
        writefilename = filename
    print writefilename
    getTabs(filename)
    createLists(filename)
    writeCode(writefilename)
if __name__ == "__main__":
    argv = sys.argv[1:]
    if len(argv) == 1:
        do(argv[0])
    elif len(argv) == 2:
        do(argv[0],argv[1])
    else:
        print "Invalid amount of arguments passed"
        help()
Ohloh | Mein Blog | Jabber: segfaulthunter@swissjabber.eu | asynchia – asynchrone Netzwerkbibliothek

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Dienstag 30. Januar 2007, 18:05

Und was bringt das?

Wenn du eigene Beschränkungen in den Settern brauchst, musst du sie doch sowieso von Hand schreiben. Oder willst du nur Java in Python programmieren?
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Benutzeravatar
name
User
Beiträge: 254
Registriert: Dienstag 5. September 2006, 16:35
Wohnort: Wien
Kontaktdaten:

Dienstag 30. Januar 2007, 19:52

Naja, spart ein paar zeilen tippen :)
Ohloh | Mein Blog | Jabber: segfaulthunter@swissjabber.eu | asynchia – asynchrone Netzwerkbibliothek

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dienstag 30. Januar 2007, 21:09

Ich schreibe meinen Code auch lieber, anstatt dasss ich seltsame Inline-Kommentare verwende und sie dann durch einen Codegenerator schicke.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Mittwoch 31. Januar 2007, 17:12

Bitte PEP8 lesen und größtenteils befolgen!

Ansonsten: Ich schreibe meinen Code lieber auch selber. Die par Zeile mehr Schreibaufwand sind zu verschmerzen. ;)

lg
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Freitag 2. Februar 2007, 07:31

name hat geschrieben:Naja, spart ein paar zeilen tippen :)
Ich habe noch !nie! einen Getter/Setter gebraucht er nur Daten setzt wie unter Java. Dafür haben wir Attribute. Wenn man Properties braucht dann kommt man ums selberschreiben nicht herum...
TUFKAB – the user formerly known as blackbird
Benutzeravatar
name
User
Beiträge: 254
Registriert: Dienstag 5. September 2006, 16:35
Wohnort: Wien
Kontaktdaten:

Freitag 2. Februar 2007, 13:24

blackbird hat geschrieben:
name hat geschrieben:Naja, spart ein paar zeilen tippen :)
Ich habe noch !nie! einen Getter/Setter gebraucht er nur Daten setzt wie unter Java. Dafür haben wir Attribute. Wenn man Properties braucht dann kommt man ums selberschreiben nicht herum...
Die get/set/del methoden muss man ja selber umschreiben, nur es generiert halt ein Geruest, sozusagen
Ohloh | Mein Blog | Jabber: segfaulthunter@swissjabber.eu | asynchia – asynchrone Netzwerkbibliothek

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Freitag 2. Februar 2007, 18:51

name hat geschrieben:Die get/set/del methoden muss man ja selber umschreiben, nur es generiert halt ein Geruest, sozusagen
Macht Vim für mich... property<tab>my_property<tab> generiert das hier:

Code: Alles auswählen

    def get_my_property(self):
        pass

    def set_my_property(self, value):
        pass

    my_property = property(get_my_property, set_my_property)
    del get_my_property, set_my_property
TUFKAB – the user formerly known as blackbird
Marten2k
User
Beiträge: 4
Registriert: Mittwoch 25. Januar 2006, 18:48

Samstag 3. Februar 2007, 19:42

Hallo,

sowas kann man sehr elegant mit Metklassen realisieren. Mit einer Metaklasse kann man die eigentliche Klasse modifizieren. Jede Klasse verwendet standardmäßig die Klasse 'type', man kann aber auch eine eigene Metaklasse schreiben.

Hier mal ein Beispiel. Es handelt sich um eine Teil einer Lohn-Berechnungsklasse. Es wird automatisch aus dem setzGib Dictonary zum Beispiel:
1. self._bruttoLohn
2. gibBruttoLohn(self): retun self._bruttoLohn
3. setzBruttoLohn(self, value): self._bruttoLohn = value

Code: Alles auswählen

# === Metaklasse lohnMeta und Funktionen ===
def erzeugeGibMethode(attributName, dct):
    """ Erzeugt aus dem uebergebenen AttributNamen eine
    gib-Methode.
    """
    def _gibMethode(self):
        return getattr(self, "_"+attributName)
    methodenName = "gib%s%s"%(attributName.upper()[0], attributName[1:])
    dct[methodenName] = _gibMethode

def erzeugeSetzMethode(attributName, startWert, dct):
    """ Erzeugt aus dem uebergebenen Attributnamen eine setz-Methode,
    und das Attribute mit dem entsprechenden Start-Wert.
    """
    def _setzMethode(self, value):
        setattr(self, "_"+attributName, value)
        return self
    methodeName = "setz%s%s"%(attributName.upper()[0], attributName[1:])
    dct["_"+attributName] = startWert
    dct[methodeName] = _setzMethode
    
class lohnMeta(type):
    """ Diese Metaklasse erzeugt in der entsprechenden lohn-Klasse
    die in setzGibtAttribute und gibAttribute deklarierten Attribute
    mit den entsprechenden Funktionen, Startwerten usw.
    """
    def __new__(cls, name, bases, dct):
        # setzGibAttribute holen
        for attributName, attributWert in dct.get('_setzGibAttribute', {}).items():
            erzeugeGibMethode(attributName, dct)
            erzeugeSetzMethode(attributName, attributWert, dct)        

        return type.__new__(cls, name, bases, dct)

# === Lohn-Klasse ===
class lohn(object):
    """ Klasse die einen Lohn repraesentiert und
    aus einem Bruttolohn einen Nettolohn berechnen
    kann.
    """
    # Attribute fuer die Metaklasse, damit die
    # setz/gib-Funktionen erzeugt werden
    # 
    # Erzeugt werden fuer die setzGibAttribute:
    # self._<key> = <value>
    # def setz<Key>(self, <key>) : self._<key> = <key>
    # def gib<Key>(self): return self._<key>
    #
    _setzGibAttribute = {'bruttoLohn' : None, 
                         'steuerKlasse' : 1, 
                         'zahleKirchenSteuer' : False,
                         'krankenVersicherungProzent' : 12.6,
                         'zahleKrankenVersicherungsZuschlag' : True,
                         'geburtsJahr' : 1973, 
                         'kinderFreiBetrag' : 0, 
                         'zeitRaum' : MONAT,
                         'bundesLand' : 'Niedersachsen',
                         'berechnungsJahr': 2007}

    # Metaklasse erzeugt die gib- und setz-Methoden zu
    # den oben erzeugten Attributen
    __metaclass__ = lohnMeta
Gruss Marten
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Sonntag 4. Februar 2007, 02:56

Aber bitte nicht Getters/Setters/Fuxors vergessen.

Ganz pauschal auf Verdacht und Vorausschau property-Methoden zu generieren ist jedenfalls nicht sehr sauber, falls du das vorgehabt haben solltest.
Antworten