Hallo Zusammen,
da es beide Themen betrifft, setze ich das unter Allgemeine Fragen.
eine Abfrage mittels SQLAlchemy und transferieren in ein WxGrid zum viewen ist problemlos. Was aber, wenn ich die Datensätze im Grid verändern, löschen oder hinzufügen will?! Meine Suche nach einer direkten Verbindung hat nichts ergeben. Muss ich tatsächlich alles "manuell" Überwachen und entsprechend reagieren, oder gibt es eine bequemere Methode, die Datenbank upzudaten?
Danke und Grüße.
WxGrid und SQLAlchemy
Wenn wx keine expliziten SQL Widgets anbiete5 (Qt macht das, aber dann ist sqlalchemy draussen, auch bei wx), dann wirst du das selbst programmieren müssen. In Python sollte es aber kein Problem sein, da einen generischen Ansatz zu entwickeln, der das einmal für alle löst.
-
- User
- Beiträge: 179
- Registriert: Dienstag 29. Dezember 2009, 00:09
Mir fehlt eigentlich ein grundlegender Ansatz. Ich habe eine Liste von Objekten , deren properties ich in String Format in das Grid bringe. Danach fehlt mir jeglicher Zusammenhang. Ich könnte 1:1 über das Grid iterieren und mit der Liste der Objekte vergleichen. Das aber würde schon dann nicht mehr funktionieren, wenn das Grid z.b. sortiert würde, da dann schon die Zuordnung zerstört ist.
Unabhängig davon eine zweite Frage; ich verstehe den gegnerischen Ansatz nicht, bzw wie würde der dabei helfen? Überhaupt wusste ich nicht, dass es bei dynamisch typisierten sprachen überhaupt generics gibt. Recherche hat ergeben, dass das mit dem typing Modul möglich ist, meintest du das?
Danke und Gruß.
Unabhängig davon eine zweite Frage; ich verstehe den gegnerischen Ansatz nicht, bzw wie würde der dabei helfen? Überhaupt wusste ich nicht, dass es bei dynamisch typisierten sprachen überhaupt generics gibt. Recherche hat ergeben, dass das mit dem typing Modul möglich ist, meintest du das?
Danke und Gruß.
- __blackjack__
- User
- Beiträge: 14078
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@mechanicalStore: Das klingt so als wenn Du Objekte in das WxGrid steckst, da dann bearbeitest und danach wieder die Werte aus der GUI in Objekte bringen oder damit abgleichen willst. Das wäre in der Tat aufwändig bis unmöglich. Du musst Dir zu jeder Zeile das dazugehörige Objekt merken und bei Änderungen auch gleich das Objekt ändern. Beim sortieren müssen die Objekte mitsortiert werden. Es würde sich anbieten da was von `wxGridTableBase` abzuleiten, was in wx quasi das Model zum View (`wxGrid`) ist.
Generischer Ansatz nicht als „generics“ im Sinne von Typdeklaration, sondern einfach ein Ansatz der nicht für spezielle Objekte gemacht ist, sondern allgemein für SQLAlchemy-ORM-Objekte. Die haben ja eine ganze Menge Metainformation wie Attributnamen, Datentypen, Defaultwerte, und so weiter, die man in Python alle zur Laufzeit abfragen kann. Also ist es möglich eine Klasse zu schreiben, die eine Liste mit beliebigen (gleichartigen) SQLAlchemy-ORM-Objekten bekommt, und die in einer Tabelle darstellt/bearbeitbar macht.
Generischer Ansatz nicht als „generics“ im Sinne von Typdeklaration, sondern einfach ein Ansatz der nicht für spezielle Objekte gemacht ist, sondern allgemein für SQLAlchemy-ORM-Objekte. Die haben ja eine ganze Menge Metainformation wie Attributnamen, Datentypen, Defaultwerte, und so weiter, die man in Python alle zur Laufzeit abfragen kann. Also ist es möglich eine Klasse zu schreiben, die eine Liste mit beliebigen (gleichartigen) SQLAlchemy-ORM-Objekten bekommt, und die in einer Tabelle darstellt/bearbeitbar macht.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
-
- User
- Beiträge: 179
- Registriert: Dienstag 29. Dezember 2009, 00:09
Mir fehlt irgendwie der wesentliche Punkt. Ich habe hier und da ein wenig recherchiert, nach Beispielen gesucht, z.B. hier:__blackjack__ hat geschrieben: Mittwoch 1. Juni 2022, 13:10 Also ist es möglich eine Klasse zu schreiben, die eine Liste mit beliebigen (gleichartigen) SQLAlchemy-ORM-Objekten bekommt, und die in einer Tabelle darstellt/bearbeitbar macht.
http://www.java2s.com/Tutorial/Python/0 ... leBase.htm
Was mir das aber nicht erklärt, denn ob ich nun strings in die Zellen von wxgrid schreibe, oder in die zugrunde liegende GridTableBase in anderem Format:
Code: Alles auswählen
class GenericTable(wx.grid.PyGridTableBase):
def __init__(self, data, rowLabels=None, colLabels=None):
wx.grid.PyGridTableBase.__init__(self)
self.data = data
...
...
data = (("A", "B"),
("C", "D"),
("E", "F"),
....
Auch wenn die Frage hier nicht gerne gehört wird, aber hast Du einen minimalen Ansatz, der mir weiter helfen könnte, bzw. der mir auf die Sprünge hilft? Generell müsste ich doch die ORM-Objekte im Grid speichern, sonst fehlt doch nach wie vor die Zuordnung?!
Danke und Gruß
- __blackjack__
- User
- Beiträge: 14078
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@mechanicalStore: Ja klar musst Du die ORM-Objekte in dem von `wx.GridTableBase` abgeleiteten Typ speichern. Und die ganzen relevanten Methoden so implementieren, dass sie das passende machen. Dazu ist diese Klasse ja da: dem `wx.Grid` eine Datenquelle so präsentieren, dass es damit etwas anfangen kann, also zwischen `wx.Grid` und Datenquelle zu vermitteln.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
-
- User
- Beiträge: 179
- Registriert: Dienstag 29. Dezember 2009, 00:09
Ein paar Fragmente zusammen gefriemelt, funktioniert alleine das schon nicht:
Hier der minimale Ansatz zum Testen:
Die LabelValues zu setzen sollte doch auf jeden Fall funktionieren ?!
(Editiert 13:35)
Code: Alles auswählen
.....
self.SetRowLabelValue(0, "Project")
self.SetRowLabelValue(1, "Netplan")
....
Code: Alles auswählen
#!/usr/bin/env python3
from sqlalchemy import (
INTEGER,
TEXT,
Column,
create_engine,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker
import wx
import wx.grid
Base = declarative_base()
Session = sessionmaker()
session = 0
class Project(Base):
__tablename__ = "project"
id = Column(INTEGER, primary_key=True)
name = Column(TEXT, nullable=False, unique=True)
netplan = Column(TEXT, nullable=False)
description = Column(TEXT, nullable=True)
class DerivedGridTable(wx.grid.GridTableBase):
def __init__(self, *args, **kwds):
wx.grid.GridTableBase.__init__(self, *args, **kwds)
self.SetRowLabelValue(0, "Project")
self.SetRowLabelValue(1, "Netplan")
# wxGlade
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
# begin wxGlade: MyFrame.__init__
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((350, 300))
self.SetTitle("frame")
self.panel_1 = wx.Panel(self, wx.ID_ANY)
sizer_1 = wx.BoxSizer(wx.VERTICAL)
self.grid_1 = wx.grid.Grid(self.panel_1, wx.ID_ANY, size=(1, 1))
self.grid_1.CreateGrid(10, 2)
self.table_1 = DerivedGridTable()
self.grid_1.SetTable(self.table_1)
sizer_1.Add(self.grid_1, 4, wx.ALL | wx.EXPAND, 5)
self.panel_1.SetSizer(sizer_1)
self.Layout()
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, wx.ID_ANY, "")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
def main():
engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(engine)
session = Session(bind=engine)
# Testdaten
for i in range(5):
project = Project(name = f"Projekt {i}", netplan = f"Netplan {i}")
session.add(project)
session.commit()
# Testdaten anzeigen
for project_name, project_netplan in (
session.query(Project.name, Project.netplan)
.all()
):
print(project_name, project_netplan)
app = MyApp(0)
# app.frame.grid_1
app.MainLoop()
if __name__ == "__main__":
main()
(Editiert 13:35)
- __blackjack__
- User
- Beiträge: 14078
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@mechanicalStore: Nirgendwo in dem Code wird die Verbindung zwischen dem Model und dem View hergestellt. Und wenn Du das tust, bekommst Du Fehlermeldungen weil Du mindestens die abstrakten Methoden implementieren musst. Das Grid muss ja irgendwo die Daten her bekommen, deswegen schreibt man ja die Model-Klasse.
`SetRowLabelValue()` bringt nichts weil die Default-Implementierung nichts macht. `GetRowLabelValue()` ist die Methode die Du implementieren musst wenn Du die Zeilen-Label beeinflussen willst, denn das ist ja die Methode die das Grid aufruft um an diese(n) Wert(e) zu kommen.
Beispiel mit festen Werten:
Und das muss man halt so umschreiben, dass sich das auf irgendeine Datenstruktur bezieht, beispielsweise eine Liste mit Objekten. So das dann die `GetNumberCols()` die Länge der Liste liefert und `GetValue()` den entsprechenden Wert des entsprechenden Attributs von dem Objekt am Index.
`SetRowLabelValue()` bringt nichts weil die Default-Implementierung nichts macht. `GetRowLabelValue()` ist die Methode die Du implementieren musst wenn Du die Zeilen-Label beeinflussen willst, denn das ist ja die Methode die das Grid aufruft um an diese(n) Wert(e) zu kommen.
Beispiel mit festen Werten:
Code: Alles auswählen
class DerivedGridTable(wx.grid.GridTableBase):
def __init__(self):
wx.grid.GridTableBase.__init__(self)
self.row_labels = ["Project", "Netplan"]
def GetNumberRows(self):
return len(self.row_labels)
def GetNumberCols(self):
return 3
def GetRowLabelValue(self, index):
return self.row_labels[index]
def GetValue(self, row_index, column_index):
return f"{row_index}, {column_index}"
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
-
- User
- Beiträge: 179
- Registriert: Dienstag 29. Dezember 2009, 00:09
Das stimmt, da gibt es noch keine Verbindung. Ich wollte erst mal die Verbindung zwischen GridTableBase und dem Grid selbst testen, indem ich minimal die Labels verändern wollte (wieso das nicht ging, ist mir jetzt klar geworden, hoffe ich).__blackjack__ hat geschrieben: Donnerstag 9. Juni 2022, 13:00 @mechanicalStore: Nirgendwo in dem Code wird die Verbindung zwischen dem Model und dem View hergestellt.
Ja, dass die virtuals implementiert werden müssen, ist mir klar, das hatte ich übersehen, nach dem Posten hier aufgrund der Fehlermeldungen implementiert.__blackjack__ hat geschrieben: Donnerstag 9. Juni 2022, 13:00 Und wenn Du das tust, bekommst Du Fehlermeldungen weil Du mindestens die abstrakten Methoden implementieren musst.
Genau darüber bin ich nun gestolpert. Ich ging davon aus, dass die GridTableBase das Model zum Grid bildet und dass das Grid immer anzeigt, was das Model gerade macht (dynamisch/automatisch?) und diese in Zusammenhang stehen (das stimmt ja auch so). Aber wenn ich in der Klasse GridTableBase set und get implementiere, dann dachte ich, dass set etwas im Grid (also in der view) setzt und vice versa get etwas aus dem Grid abruft. Aber es scheint genau umgekehrt?!__blackjack__ hat geschrieben: Donnerstag 9. Juni 2022, 13:00 `SetRowLabelValue()` bringt nichts weil die Default-Implementierung nichts macht. `GetRowLabelValue()` ist die Methode die Du implementieren musst wenn Du die Zeilen-Label beeinflussen willst, denn das ist ja die Methode die das Grid aufruft um an diese(n) Wert(e) zu kommen.
Edit: Ergo, woher weiß das Grid (die View), dass / wann es die einzelnen Funktionen der GridTableBase (also alle get's) aufrufen soll?
- __blackjack__
- User
- Beiträge: 14078
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@mechanicalStore: Die Antwort auf das Edit ist vielleicht ein bisschen doof, aber das Grid weiss das weil das so programmiert ist. Es fragt halt immer GridTableBase wenn es was über die Daten wissen muss um die darzustellen.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
-
- User
- Beiträge: 179
- Registriert: Dienstag 29. Dezember 2009, 00:09
Na, die Frage war ja auch doof...
Fakt ist also, dass sich das Grid (die view) ständig anhand der GridTableBase eigenständig updated?
Und wenn ich im Grid einen Wert ändere, müsste ich also im cell_changing event des Grid die (überschriebene) methode SetValue der GridTableBase aufrufen und den neuen Wert an diese übergeben?! Oder gibt es da auch wiederum (einen umgekehrten) Automatismus?
Fakt ist also, dass sich das Grid (die view) ständig anhand der GridTableBase eigenständig updated?
Und wenn ich im Grid einen Wert ändere, müsste ich also im cell_changing event des Grid die (überschriebene) methode SetValue der GridTableBase aufrufen und den neuen Wert an diese übergeben?! Oder gibt es da auch wiederum (einen umgekehrten) Automatismus?
-
- User
- Beiträge: 179
- Registriert: Dienstag 29. Dezember 2009, 00:09
Oh Mann... jetzt beschwert sich SQLAlchemy, wenn ich einen Wert ändern will (innerhalb SetValue), was ich nicht verstehen kann:
Der Übersicht halber das ganze Testprogramm:Traceback (most recent call last):
File "c:\Users\*****\Documents\Develop\Python\SU3\test2.py", line 60, in SetValue
self.my_list[row_index].netplan = string_text
File "C:\Users\*****\AppData\Local\Programs\Python\Python39\lib\site-packages\sqlalchemy\engine\row.py", line 219, in __setattr__
raise AttributeError("can't set attribute")
AttributeError: can't set attribute
Code: Alles auswählen
#!/usr/bin/env python3
from sqlalchemy import (
INTEGER,
TEXT,
Column,
create_engine,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker
import wx
import wx.grid
Base = declarative_base()
Session = sessionmaker()
session = 0
class Project(Base):
__tablename__ = "project"
id = Column(INTEGER, primary_key=True)
name = Column(TEXT, nullable=False, unique=True)
netplan = Column(TEXT, nullable=False)
description = Column(TEXT, nullable=True)
class DerivedGridTable(wx.grid.GridTableBase):
def __init__(self):
wx.grid.GridTableBase.__init__(self)
self.col_labels = ["Project", "Netplan", "Description"]
self.my_list = []
for project in (
session.query(Project.name, Project.netplan, Project.description)
.all()
):
self.my_list.append(project)
def GetColLabelValue(self, index):
return self.col_labels[index]
def GetNumberCols(self):
return len(self.col_labels)
def GetNumberRows(self):
return len(self.my_list)
def GetValue(self, row_index, column_index):
if column_index == 0:
return self.my_list[row_index].name
elif column_index == 1:
return self.my_list[row_index].netplan
elif column_index == 2:
return self.my_list[row_index].description
# return f"{row_index}, {column_index}"
def SetValue(self, row_index, column_index, string_text):
if column_index == 0:
self.my_list[row_index].name = string_text
elif column_index == 1:
self.my_list[row_index].netplan = string_text
elif column_index == 2:
self.my_list[row_index].description = string_text
# Test, ob DB aktuell
for project in (
session.query(Project.name, Project.netplan, Project.description)
.all()
):
print(project.name, project.netplan, project.description)
# wxGlade
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
# begin wxGlade: MyFrame.__init__
kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((350, 300))
self.SetTitle("frame")
self.panel_1 = wx.Panel(self, wx.ID_ANY)
sizer_1 = wx.BoxSizer(wx.VERTICAL)
self.grid_1 = wx.grid.Grid(self.panel_1, wx.ID_ANY, size=(1, 1))
self.grid_1.CreateGrid(10, 2)
self.table_1 = DerivedGridTable()
self.grid_1.SetTable(self.table_1)
sizer_1.Add(self.grid_1, 4, wx.ALL | wx.EXPAND, 5)
self.panel_1.SetSizer(sizer_1)
self.Layout()
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, wx.ID_ANY, "")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
def main():
global session
engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(engine)
session = Session(bind=engine)
# Testdaten
for i in range(5):
project = Project(name = f"Projekt {i}", netplan = f"Netplan {i}", description = f"Description {i}")
session.add(project)
session.commit()
# Testdaten anzeigen
for project in (
session.query(Project.name, Project.netplan, Project.description)
.all()
):
print(project.name, project.netplan, project.description)
app = MyApp(0)
# app.frame.grid_1
app.MainLoop()
if __name__ == "__main__":
main()
- __blackjack__
- User
- Beiträge: 14078
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@mechanicalStore: Naja das sind halt so etwas wie `namedtuple` und es macht aus ORM-Sicht auch keinen Sinn da Werte zu setzen. Du müsstest in `my_list` (sehr schlechter Name) ORM-Objekte vom Typ `Project` speichern, dann kann man auch die Attribute setzen.
`session` auf Modulebene hat da nix zu suchen. Und das mit der Zahl 0 zu initialisieren und dann später durch ein Sitzungs-Objekt zu ersetzen ist noch mal zusätzlich verwirrend.
`all()` liefert bereits eine Liste, da muss man nicht noch mal in einer Schleife jedes Element in einer andere Liste stecken.
Überarbeitet:
ACHTUNG: Die Testausgabe nach dem setzen des Attributs ist irreführend! Das bezieht sich nur auf diese Transaktion, die Daten sind tatsächlich erst in der Datenbank wenn man auch `commit()` aufgerufen hat!
`session` auf Modulebene hat da nix zu suchen. Und das mit der Zahl 0 zu initialisieren und dann später durch ein Sitzungs-Objekt zu ersetzen ist noch mal zusätzlich verwirrend.
`all()` liefert bereits eine Liste, da muss man nicht noch mal in einer Schleife jedes Element in einer andere Liste stecken.
Überarbeitet:
Code: Alles auswählen
#!/usr/bin/env python3
import wx
import wx.grid
from sqlalchemy import INTEGER, TEXT, Column, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
Session = sessionmaker()
class Project(Base):
__tablename__ = "project"
id = Column(INTEGER, primary_key=True)
name = Column(TEXT, nullable=False, unique=True)
netplan = Column(TEXT, nullable=False)
description = Column(TEXT, nullable=True)
class DerivedGridTable(wx.grid.GridTableBase):
def __init__(self, session):
wx.grid.GridTableBase.__init__(self)
self.session = session
self.col_labels = ["Project", "Netplan", "Description"]
self.attributes = ["name", "netplan", "description"]
self.projects = self.session.query(Project).all()
def GetColLabelValue(self, index):
return self.col_labels[index]
def GetNumberCols(self):
return len(self.col_labels)
def GetNumberRows(self):
return len(self.projects)
def GetValue(self, row_index, column_index):
return getattr(self.projects[row_index], self.attributes[column_index])
def SetValue(self, row_index, column_index, text):
setattr(self.projects[row_index], self.attributes[column_index], text)
# Test, ob DB aktuell
for project in self.session.query(Project).all():
print(project.name, project.netplan, project.description)
class Frame(wx.Frame):
def __init__(self, session, *args, **kwds):
wx.Frame.__init__(self, *args, **kwds)
self.SetSize((350, 300))
self.SetTitle("frame")
self.panel_1 = wx.Panel(self, wx.ID_ANY)
sizer_1 = wx.BoxSizer(wx.VERTICAL)
self.grid_1 = wx.grid.Grid(self.panel_1, wx.ID_ANY, size=(1, 1))
self.grid_1.CreateGrid(10, 2)
self.table_1 = DerivedGridTable(session)
self.grid_1.SetTable(self.table_1)
sizer_1.Add(self.grid_1, 4, wx.ALL | wx.EXPAND, 5)
self.panel_1.SetSizer(sizer_1)
self.Layout()
def main():
engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(engine)
session = Session(bind=engine)
# Testdaten
for i in range(5):
project = Project(
name=f"Projekt {i}",
netplan=f"Netplan {i}",
description=f"Description {i}",
)
session.add(project)
session.commit()
# Testdaten anzeigen
for project in session.query(Project).all():
print(project.name, project.netplan, project.description)
app = wx.App()
frame = Frame(session, None, wx.ID_ANY, "")
frame.Show()
app.SetTopWindow(frame)
app.MainLoop()
if __name__ == "__main__":
main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
-
- User
- Beiträge: 179
- Registriert: Dienstag 29. Dezember 2009, 00:09
Das habe ich doch gemacht, oder....__blackjack__ hat geschrieben: Freitag 10. Juni 2022, 13:03 @mechanicalStore: Naja das sind halt so etwas wie `namedtuple` und es macht aus ORM-Sicht auch keinen Sinn da Werte zu setzen. Du müsstest in `my_list` (sehr schlechter Name) ORM-Objekte vom Typ `Project` speichern, dann kann man auch die Attribute setzen.
...war die doppelte Liste das Problem?__blackjack__ hat geschrieben: Freitag 10. Juni 2022, 13:03 `all()` liefert bereits eine Liste, da muss man nicht noch mal in einer Schleife jedes Element in einer andere Liste stecken.
Code: Alles auswählen
def GetValue(self, row_index, column_index):
return getattr(self.projects[row_index], self.attributes[column_index])
def SetValue(self, row_index, column_index, text):
setattr(self.projects[row_index], self.attributes[column_index], text)
Code: Alles auswählen
return getattr( (self.projects[row_index]).(self.attributes[column_index]) )
- __blackjack__
- User
- Beiträge: 14078
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@mechanicalStore: Du hast nicht `Project`-Objekte abgefragt sondern (Named-)Tupel mit drei expliziten Attributwerten von `Project`-Objekten. Da kommt am Ende eher so etwas wie eine traditionelle Abfrage mit ”dummen” Ergebnissen heraus, und keine ORM-Objekte. Bei Deiner Abfrage war ja auch gar keine ID dabei, das heisst selbst wenn das irgendwie gehen sollte, hätte man ja gar keine Zuordnung mehr zu dem Datensatz herstellen können.
Das mit dem `all()` war kein wirkliches Problem, es ist halt nur unnötig die Liste noch mal in einer andere Liste umzukopieren.
Wie willst Du denn mit einem Argument bei `getattr()` auskommen? Das ist eine ganz normale Funktion. Das was Du da als „so müsste es aussehen“ hingeschrieben hast ist syntaktisch kein gültiges Python. Hinter dem Punkt-Operator muss ein Name stehen, literal im Quelltext, und kein Ausdruck. Die `getattr()`-Funktion braucht zwei Argumente: das Objekt und den Namen des Attributs als Zeichenkette. Wie sollte das mit weniger Argumenten gehen? Wenn das so ginge wie Du das geschrieben hast, wozu bräuchte man dann noch die `getattr()`-Funktion?
Das mit dem `all()` war kein wirkliches Problem, es ist halt nur unnötig die Liste noch mal in einer andere Liste umzukopieren.
Wie willst Du denn mit einem Argument bei `getattr()` auskommen? Das ist eine ganz normale Funktion. Das was Du da als „so müsste es aussehen“ hingeschrieben hast ist syntaktisch kein gültiges Python. Hinter dem Punkt-Operator muss ein Name stehen, literal im Quelltext, und kein Ausdruck. Die `getattr()`-Funktion braucht zwei Argumente: das Objekt und den Namen des Attributs als Zeichenkette. Wie sollte das mit weniger Argumenten gehen? Wenn das so ginge wie Du das geschrieben hast, wozu bräuchte man dann noch die `getattr()`-Funktion?
Code: Alles auswählen
In [216]: class Class:
...: def __init__(self, answer):
...: self.answer = answer
...:
In [217]: instance = Class(42)
In [218]: instance."answer"
File "<ipython-input-218-0cfb99b48ec5>", line 1
instance."answer"
^
SyntaxError: invalid syntax
In [219]: getattr(instance."answer")
File "<ipython-input-219-e8dfc2209bbe>", line 1
getattr(instance."answer")
^
SyntaxError: invalid syntax
In [220]: getattr(instance, "answer")
Out[220]: 42
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
-
- User
- Beiträge: 179
- Registriert: Dienstag 29. Dezember 2009, 00:09
@__blackjack__:Soweit alles verstanden, auch mit den namedtuple, leuchtet ein. Was getattr betrifft, da habe ich mir selbst ein Missverständnis eingebaut. Ich habe nämlich hier nachgesehen:
https://docs.wxpython.org/wx.grid.GridT ... e.GetAttr
Klar, dass ich damit dann auf dem Holzweg war. Aber wenn man es vor diesem Hintergrund betrachtet, war meine Frage ja nicht ganz so unsinnig.
https://docs.wxpython.org/wx.grid.GridT ... e.GetAttr
Klar, dass ich damit dann auf dem Holzweg war. Aber wenn man es vor diesem Hintergrund betrachtet, war meine Frage ja nicht ganz so unsinnig.
