2

我正在使用 Python 的 ctypes 来连接一个 C 库文件,运行ctypesgen来创建一个我可以导入的包装模块(例如,api.py)。碰巧许多 C 函数和宏的名称都以双下划线开头,Python 将其视为“私有”,并在用于类定义时调用名称修饰。

例如,这有效:

import api
api.__someGetter()

但这并不

import api
class MyClass(object):
    i = api.__someGetter()

AttributeError: 'module' object has no attribute '_MyClass__someGetter'

确实有效:

i = api.__dict__['__someGetter']()

但它对我来说似乎不是很优雅或易于阅读 - 代码将充满对字典键的调用。

有没有更好的方法来禁用或解决模块的名称修改?

(它是一个 C 库的事实可能与答案无关,但希望它解释了为什么我不能只更改命名约定。)

4

2 回答 2

2

您可以在 Python 中重新导出名称,将双下划线转换为单下划线。

import api
for name in api.__dict__:
    if name.startswith('__'):
        globals()[name[1:]] = api.__dict__[name]

这会将api当前模块中的所有双下划线更改为单下划线。然后可以从另一个模块导入该模块。

注意:在 C 中命名以下划线开头的函数是不正确的。请参阅 n1526 的第 7.1.3 节“保留标识符”。在 C 中使用以双下划线开头的名称是“未定义的行为”,这是“不要这样做”的技术术语。

于 2012-07-27T02:52:46.073 回答
1

出于好奇,这里有一种实现这种效果的方法。它将模块包装在一个类中,该类具有自定义属性访问方法,该方法仅丢弃损坏名称的第一部分。这肯定有点小技巧,并且可能并非在所有情况下都有效——我不建议认真使用它!

    class Wrapper(object):
        def __init__(self, module):
            for name in module.__dict__:
                self.__dict__[name] = module.__dict__[name]

        #__getattr__ is called only if regular access failed
        def __getattr__(self, name): 
            try:
                return self.__dict__['__'+name.split('__', 1)[1]]
            except (IndexError, KeyError):
                raise AttributeError, name

        def __setattr__(self, name, value):
            try:
                self.__dict__['__'+name.split('__', 1)[1]] = value
            except IndexError:   #no double underscores to split
                self.__dict__[name] = value

用法:

import cwrapper 
api = Wrapper(cwrapper)

class MyClass(object):
    i = api.__some_Getter() #works
于 2012-07-28T03:14:47.543 回答