La référence de la fonction Python transmise dans le constructeur se transforme en type de données C_Void_P
Question
Pour faire une longue histoire, j'essaie de passer une liste de dictionnaires dans une classe de conteneurs, avec l'intention que chaque dictionnaire soit utilisé pour instancier une autre classe. Le problème est que chaque dictionnaire contient une référence d'objet de fonction à attribuer à la sous-classe, et pour une raison quelconque juste avant que la sous-classe la plus intérieure ne soit instanciée, elle change d'un objet de fonction Python dans un objet C_Void_P.
Le domaine d'application est la création d'une bibliothèque de widgets d'interface utilisateur basés sur du texte à l'aide de malédictions.
Voici la classe «enfant» que le conteneur est censé contenir:
class DigitalReadout(Window):
# Just a one-line borderless window displaying some data...
def __init__(self, width, y, x, label, digits, data_source, parent=None):
super(DigitalReadout, self).__init__(1, width, y, x, parent)
self.data_source = data_source
self.data = self.get_data_from_source()
self.label = label
self.digits = digits
self.spaces = self.width - len(self.label) - self.digits # Calc Number of extra spaces
###Irrelevant display-related classes omitted###
def update_data(self):
self.data = self.get_data_from_source() #return data from function
def get_data_from_source(self):
return self.data_source.__call__()
Et voici la classe «conteneur»:
class ReadoutPanel(BoxedWindow):
def __init__(self, y, x, readouts, parent=None):
super(ReadoutPanel,self).__init__(2 + len(readouts), self.find_longest_readout_width(readouts) + 2, y, x, parent)
self.children = []
self.initialize_readouts(readouts)
def find_longest_readout_width(self, readouts):
#Find the longest member and size container accordingly
longest_length = 0
for each_dict in readouts:
this_dict_length = each_dict['digits'] + len(each_dict['label']) + 1
if this_dict_length > longest_length:
longest_length = this_dict_length
return longest_length
def initialize_readouts(self, readouts):
y_readout_index = 1
for each_hash in readouts:
function = each_dict['func']
function()
self.children.append(DigitalReadout(each_dict['digits'] + len(each_dict['label']) + 1,
1,
y_readout_index,
1,
function,
self.window))
Pour référence, la fenêtre des classes de base et BoxedWindow peuvent être affichés ici
Lorsque j'exécute le code de test suivant, j'obtiens l'erreur suivante:
if __name__ == '__main__':
#standard cuses initialization here...
from time import clock
i = 0
def print_i():
return str(i)
readouts = [{'label': 'count',
'digits': 10,
'func': print_i},
{'label': 'clock',
'digits':10,
'func': print_i}]
readout_panel = ReadoutPanel(1, 1, readouts) #Initialize that puppy!
curses.endwin()
Erreur:
Traceback (most recent call last):
File "window.py", line 515, in <module>
readout_panel = ReadoutPanel(1, 1, readouts)
File "window.py", line 455, in __init__
self.initialize_readouts(readouts)
File "window.py", line 476, in initialize_readouts
self.window))
File "window.py", line 183, in __init__
self.data = self.data_source()
TypeError: 'c_void_p' object is not callable
Printlining révèle que la fonction est récupérée à partir du dictionnaire et est toujours un objet de fonction. Une fois qu'il est passé dans le constructeur de DigitalReadout, cependant, il revient en quelque sorte un objet C_Void_P. Des idées pourquoi cela se produit?
Merci d'avance et excuses pour la question horriblement longue.
La solution
Ceci est le constructeur de DigitalReadout
:
def __init__(self, width, y, x, label, digits, data_source, parent=None)
C'est comme ça que vous l'appelez:
DigitalReadout(each_dict['digits'] + len(each_dict['label']) + 1, # width
1, # y
y_readout_index, # x
1, # label
function, # digits
self.window) # data_source
On dirait que vous manquez un paramètre dans le constructeur (height?
), parce que si je le lis bien, la fonction doit être data_source
Et c'est maintenant digits
.