Seite 1 von 1

Alle Variablen einer Klasse ändern

Verfasst: Montag 17. Juli 2017, 14:58
von RubenRybnick
Hallo,

ich habe ein komisches Problem. Ich habe eine Klasse z.B.

Code: Alles auswählen

class parameter:
  a=2
  b=[1,2,3]
  c=4
....
usw.
im Prinzip eine Klasse voll mit Variablen, welche nur Zahlen angeben. Jedoch sind manche dieser Variablen schlecht deklariert und ich hätte sie gerne als np.array.

Gibt es eine Möglichkeit alle Einträge einer Klasse durchzugehen und diese zu ändern? Ich könnte jetzt händisch hinschreiben und wenn ich meiner Funktion die parameter Übergeben habe schreiben:

Code: Alles auswählen

def brot(parameter):
 parameter.b=np.array(b)
usw.

Gibt es eine Möglichkeit für alle durchzuführen?

Re: Alle Variablen einer Klasse ändern

Verfasst: Montag 17. Juli 2017, 15:16
von BlackJack
@RubenRybnick: Das ist ja erst einmal eine komische Klasse. Warum missbrauchst Du eine Klasse für so etwas? Wenn das ein Wörterbuch wäre, hättest Du das Problem nicht.

Man könnte mit `dir()` durch die Attribute/Werte gehen und die ”magischen” rausfiltern, und mit `setattr()` die Änderungen wieder auf dem Objekt speichern.

Re: Alle Variablen einer Klasse ändern

Verfasst: Montag 17. Juli 2017, 18:57
von RubenRybnick
Hoi,

der Code war leider schon vorhanden und ich muss mich irgendwie damit abfinden. Es sind ca 5000 Zeilen Code mit Verwendung von parameter.variable und den ganzen Code zu ändern ist mir zu Stressig. Ich könnte in der Klasse selber überall np.array davor schreiben, aber ich dachte es gibt vllt eine einfache Möglichkeit um das ganze automatisiert durchzugehen :(

Re: Alle Variablen einer Klasse ändern

Verfasst: Montag 17. Juli 2017, 19:20
von nezzcarth
RubenRybnick hat geschrieben: der Code war leider schon vorhanden und ich muss mich irgendwie damit abfinden. Es sind ca 5000 Zeilen Code mit Verwendung von parameter.variable und den ganzen Code zu ändern ist mir zu Stressig. Ich könnte in der Klasse selber überall np.array davor schreiben, aber ich dachte es gibt vllt eine einfache Möglichkeit um das ganze automatisiert durchzugehen :(
Die "Klasse" zur Laufzeit (und damit bei jeder Ausführung neu!) so zurecht zu biegen, dass sie deinen Ansprüchen eher entspricht, ist meiner Meinung nach kein sinnvolles Vorgehen. Du solltest das nach Möglichkeit wirklich im Quelltext direkt abändern, auch wenn es einmalig viel Arbeit ist. Je nach Art und Umfang der Änderungen kann man das auch (semi-)automatisch machen, also z. B. mit regulären Ausdrücken in sed bzw. der Ersetzen-Funktion deines bevorzugten Editors, oder den Refactoring-Tools einer IDE wie Pycharm. Gerade die erstgenannte Variante ist natürlich nicht unkritisch, aber in solchen Fällen kann man das denke ich ausnahmsweise mal machen, wenn man vorsichtig ist.

Wenn es unbedingt sein muss, klappt es so, wie BlackJack meinte; statt dir kann man auch inspect.getmembers() zur Hilfe nehmen.

Re: Alle Variablen einer Klasse ändern

Verfasst: Mittwoch 19. Juli 2017, 08:05
von Zizibee
Ich würde für so etwas die Suche und Ersetzte Funktion vom Notepad++ benutzen. Wenn man da ein Häckchen bei Reguläre Ausdrücke setzt, kann man sich da echt austoben :)
Bei deinem Beispiel in etwa so:

Suche: =[ ]?([a-zA-Z0-9 ,\[\]\(\)]*)
Ersetze: =np.array\(\1\)

Re: Alle Variablen einer Klasse ändern

Verfasst: Mittwoch 19. Juli 2017, 14:47
von BlackJack
Etwas sicherer als reguläre Ausdrücke wäre es wahrscheinlich auf dem AST von dem Quelltext zu operieren. `redbaron` ist für Python so etwas ähnliches wie BeautifulSoup für HTML:

Code: Alles auswählen

from __future__ import absolute_import, division, print_function
from redbaron import RedBaron
from redbaron.nodes import ListNode

SOURCE = '''
class Spam:
  x=[1,2,3]

class parameter:
  a=2
  b=[1,2,3]
  c=4
  d=[
    42,
    23,
    4711,
  ]

class Parrot:
  y=[3,2,1]
'''


def is_list_node(node):
    return isinstance(node, ListNode)


def main():
    np_array_call = RedBaron('np.array()')[0]
    red = RedBaron(SOURCE)
    parameter_class = red.find('class', name='parameter')
    for assignment in parameter_class('assignment', value=is_list_node):
        new_value = np_array_call.copy()
        new_value.call.value = assignment.value
        assignment.value = new_value
    print(red.dumps())


if __name__ == '__main__':
    main()
Ausgabe:

Code: Alles auswählen

class Spam:
  x=[1,2,3]

class parameter:
  a=2
  b=np.array([1,2,3])
  c=4
  d=np.array([
    42,
    23,
    4711,
  ])

class Parrot:
  y=[3,2,1]