传递给构造函数的 Python 函数引用会变成 c_void_p 数据类型

发布于 2024-12-28 16:48:49 字数 3398 浏览 0 评论 0原文

长话短说,我试图将字典列表传递到容器类中,目的是每个字典将用于实例化另一个类。问题在于,每个字典都包含一个要分配给子类的函数对象引用,并且由于某种原因,在实例化最里面的子类之前,它从 python 函数对象变成了 c_void_p 对象。

应用程序域是使用curses 创建基于文本的UI 小部件库。

这是容器要包含的“子”类:

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__()

这是“容器”类:

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))

作为参考,可以查看基类 Window 和 BoxedWindow here

当我运行以下测试代码时,出现以下错误:

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()

错误:

 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

Printlined 显示该函数正在从字典中获取,并且仍然是一个函数对象。然而,一旦它被传递到 DigitalReadout 的构造函数中,它就会以某种方式返回一个 c_void_p 对象。有什么想法为什么会发生这种情况吗?

提前致谢,并对这个冗长的问题表示歉意。

To make a long story short, I'm trying to pass a list of dictionaries into a container class, with the intention that each dictionary will be used to instantiate another class. The problem is that each dictionary contains a function object reference to be assigned to the subclass, and for some reason just before the innermost subclass is instantiated, it changes from a python function object into a c_void_p object.

The application domain is the creation of a library of text-based UI widgets using curses.

Here is the 'child' class which the container is meant to contain:

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__()

And here is the 'container' class:

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))

For reference, the base classes Window and BoxedWindow can be viewed here

When I run the following test code, I get the subsequent error:

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()

Error:

 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 reveals that the function is being fetched from the dictionary and is still a function object. Once it gets passed into the constructor for DigitalReadout, however, it somehow comes back a c_void_p object. Any ideas why this is happening?

Thanks in advance, and apologies for the horrendously long question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绅士风度i 2025-01-04 16:48:50

这是 DigitalReadout 的构造函数:

def __init__(self, width, y, x, label, digits, data_source, parent=None)

这就是你如何调用它:

DigitalReadout(each_dict['digits'] + len(each_dict['label']) + 1, # width
                                        1,                        # y
                                        y_readout_index,          # x
                                        1,                        # label
                                        function,                 # digits
                                        self.window)              # data_source

看起来你在构造函数中缺少一个参数(height?),因为如果我正在阅读没错,函数应该是 data_source,现在是 digits

This is the constructor of DigitalReadout:

def __init__(self, width, y, x, label, digits, data_source, parent=None)

This is how you call it:

DigitalReadout(each_dict['digits'] + len(each_dict['label']) + 1, # width
                                        1,                        # y
                                        y_readout_index,          # x
                                        1,                        # label
                                        function,                 # digits
                                        self.window)              # data_source

Looks like you're missing a parameter in the constructor (height?), because if I'm reading it right, the function should be data_source and it now is digits.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文