Это связано с существующей (и довольно старой) библиотекой, в которой вызов из моей собственной программы выдает объект не имеет атрибута для чего-то, что, как мне кажется, уже существует. Исходная библиотека — ObjectListView, но я использовал версию, исправленную для Python 3, ObjectListView2, для которой я дополнительно применил оттуда локально некоторые ожидающие запросы на включение. Далее ниже представлена тестовая программа, использующая ObjectListView. Короче говоря, у меня есть список с включенными редактируемыми ячейками; в конце концов я хочу знать, была ли изменена ячейка и что было изменено. Для этого я использовал комбинацию события EVT_CELL_EDIT_FINISHING и функции GetSelectedObjects, которая, как я предполагал, должна решить мой запрос.
Запустив тестовую программу и отредактировав любую ячейку, я щелкнул мышью, чтобы принять редактирование, и получил следующую ошибку:
Traceback (самый последний вызов — последний): Файл «C:\temp\testcase.py», строка 46, в OnNotifyChange self.new_data = ObjectListView.ObjectListView.GetSelectedObjects(self) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^ Файл «C:\python31.164\Lib\site-packages\ObjectListView\ObjectListView.py», строка 1205, в GetSelectedObjects список возврата (self.YieldSelectedObjects()) ^^^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: у объекта MyFrame нет атрибута YieldSelectedObjects. Однако, если посмотреть на код ObjectListView.py, «YieldSelectedObjects» находится всего на пару строк ниже строки, вызывающей ошибку. На снимке ниже показано, как выглядит код этой библиотеки (показана только часть, представляющая интерес).
Мой вопрос: как это возможно? Я не понимаю, почему я получаю ошибку об отсутствующем атрибуте для чего-то, чего нет. Меня даже не особо волнует точный код из этого снимка, а скорее принцип «почему».
Я использую 64-разрядную версию Windows 10, 64-разрядную версию Python 3.11.3 и версию 4.2.1 msw (phoenix) wxWidgets 3.2.2.1.
#!/usr/bin/env python3 # -*- кодировка: utf-8 -*- импортировать wx импортировать ObjectListView ## класс ObjectivizeData(объект): def __init__(self, data_1, data_2): self.data_1 = данные_1 self.data_2 = данные_2 ## класс MyFrame(wx.Frame): def __init__(self, *args, **kwds): kwds["стиль"] = kwds.get("стиль", 0) | wx.DEFAULT_FRAME_STYLE wx.Frame.__init__(self, *args, **kwds) self.SetSize((400, 300)) self.SetTitle("тестовый кадр") self.all_data = ['"abc", "123"', '"def", "456"'] self.processed_data = [] для d в self.all_data: d = d.replace('"','') d = d.strip() data_1, data_2 = d.split(",") self.processed_data.append(ObjectivizeData(data_1, data_2)) self.dataOlv = ObjectListView.ObjectListView(self, wx.ID_ANY, style=wx.LC_REPORT) self.dataOlv.SetColumns([ ObjectListView.ColumnDefn("имя", "слева", 180, "данные_1"), ObjectListView.ColumnDefn("значение", "left", 180, "data_2")]) self.dataOlv.SetObjects(self.processed_data) # сделать ячейки редактируемыми self.dataOlv.cellEditMode = ObjectListView.ObjectListView.CELLEDIT_DOUBLECLICK # уведомить об изменении self.dataOlv.Bind(ObjectListView.EVT_CELL_EDIT_FINISHING, self.OnNotifyChange) def OnNotifyChange(сам, событие): распечатать («ячейка была отредактирована») # найти то, что было изменено self.new_data = ObjectListView.ObjectListView.GetSelectedObjects(self) # и т. д. ## класс MyApp(wx.App): защита OnInit (сам): self.frame = MyFrame(None, wx.ID_ANY, "") self.SetTopWindow(self.frame) self.frame.Show() вернуть истину если __name__ == "__main__": приложение = МоеПриложение(0) приложение.MainLoop()
