2

私はPythonにプライベート変数を許可させようとしているので、クラスの開始時に配置するこのデコレータを作成して、すべての関数が追加のプライベートパラメータを取得し、必要に応じて変更できるようにしました。私の知る限り、クラスの外部から変数を取得することは不可能ですが、私はプロではありません。

誰かがプライベートオブジェクトにハッキングしてそこから値を取得する方法を見つけることができますか?これよりも良い方法はありますか?

Python 2.7

#this is a decorator that decorates another decorator. it makes the decorator
#not loose things like names and documentation when it creates a new function
def niceDecorator(decorator):
    def new_decorator(f):
        g = decorator(f)
        g.__name__ = f.__name__
        g.__doc__ = f.__doc__
        g.__dict__.update(f.__dict__)
        return g
    new_decorator.__name__ = decorator.__name__
    new_decorator.__doc__ = decorator.__doc__
    new_decorator.__dict__.update(decorator.__dict__)
    return new_decorator

@niceDecorator
#this is my private decorator
def usePrivate(cls):

    prv=type('blank', (object,), {})
    #creates a blank object in the local scope
    #this object will be passed into every function in
    #the class along with self which has been renamed
    #as pbl (public).

    @niceDecorator
    #this is the decorator that gets applied to every function
    #in the class. in makes it also accept the private argument
    def decorate(func):
        def run(pub, *args, **kwargs):
            return func(pub,prv, *args, **kwargs)
        return run

    #this loops through every function in the class and applies the decorator
    for func in cls.__dict__.values():
        if callable(func):
            setattr(cls, func.__name__, decorate(getattr(cls, func.__name__)))

    return cls

#this is the class we are testing the private decorator with.
#this is what the user would program
@usePrivate
class test():

    #sets the value of the private variable
    def setValue(pbl,prv,arg):
        #pbl (public) is another name for self
        #prv (private) acts just like self except its private
        prv.test=arg

    #gets the value of the private variable
    def getValue(pbl,prv):
        return prv.test
a=test()
a.setValue(3)
print a.getValue()
4

4 に答える 4

10

要するに:これをしないでください。

Pythonで物事を本当にプライベートにする必要はありません。あなたのソフトウェアを使用している人々は、何かがプライベートとしてマークされているかどうか(変数名はで始まる_)を見ることができるので、彼らは知っています。それでもアクセスしたい場合は、なぜ停止するのですか?

あなたのコードを回避する方法もあると確信しています-Pythonには信じられないほどの量の内省的なコードがあり、クラスの変更は簡単です。誰かが本当にそれに到達したいのであれば、何かをロックダウンすることは事実上不可能です。

Pythonでは、セッター/ゲッターは無意味であることも注目に値します。目的は、属性の設定/取得に関するコードを追加できるようにすることです。これは、Pythonで組み込みのを使用property()て実行できます。

于 2012-04-28T16:02:22.540 に答える
9

これは興味深いアイデアですが、デコレータに使用しているラッパー関数のfunc_closure属性には、「プライベート」オブジェクトへの参照が含まれています。したがって、「プライベート」変数にはとしてアクセスできますa.getValue.func_closure[0].cell_contents.test。(ラップされた関数を使用して、「プライベート」オブジェクトにアクセスできますgetValue。)

一般に、この種の手法は、コードを使用している他のプログラマーを困らせるだけです。

于 2012-04-28T16:20:35.153 に答える
4

特に元のソースを読む場合は、Pythonで物事を理解する方法が常にあります。kindallの例を使用して、ファイルの最後に次の行を追加します。

print a.getValue.im_func.func_closure[0].cell_contents.test
a.getValue.im_func.func_closure[0].cell_contents.test = 17
print a.getValue()

本当に、これをしないでください。Pythonの人々が「プライベート変数を気にしないでください」と言うのには理由があります。

于 2012-04-28T16:34:52.757 に答える
1

他の人が言っているように、プライベート変数に到達する方法はまだあります。ただし、C++ではプライベート変数にアクセスできます。このC++の例を考えてみましょう。

class PrivateEye
{
    private:
    int a;
    double b;
    char c;

    public:
    // ... public functions ...
};

PrivateEye detective;

double privateB = *((double *) ((void *) &detective + sizeof(detective.a)));

ご覧のとおり、プライベート変数にアクセスするには多くの作業が必要です。そのため、それを行う人はリスクを知るのに十分な知識を持っている必要があります。したがって、_attributeプライベート属性を使用しているプログラマーがいる場合、投稿したソリューションは、プライベート属性をいじる前にプログラマーにそれについて考えさせるのに効果的です。(二重アンダースコア)を使用__attributeすると、名前のマングリングが発生します。これは、「プライベート」属性にアクセスすることを決定する前に、人々にもう少し考えさせるのと同じ効果があります。

編集:プライベートメンバーへのアクセスの2番目の回答によると、C ++標準はクラス内のメンバー変数の順序を保証しないため、C++の例で必要なプライベート変数にアクセスするには少し実験が必要になる場合がありますその上。

于 2012-07-28T04:03:11.160 に答える