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単一アンダースコアに変更されます。このモジュールは、別のモジュールからインポートできます。

注: 2つのアンダースコアで始まる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 に答える