2012-04-28 6 views
2

私はprivate変数を許可するようにしようとしています。そのため、クラスの募集に置いたデコレータを作成して、すべての関数が自分が望むものに変更できる追加のプライベートパラメータを取得するようにしました。私が言う限りでは、クラスの外から変数を取得することは不可能ですが、私はプロではありません。は本当にこのコードですか? (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() 
+5

これを*プライベートにするにはどうしてこのようなトラブルが発生しますか?このコンセプトはPythonではあまり意味がありません... – ChristopheD

+5

このコードは怖いです:( –

+5

サイドノート - 'niceDecorator'は使用しないでください' functools.wraps() 'を使用してください –

答えて

9

これは興味深い考えですが、デコレータに使用しているラッパー関数は、func_closure属性の "private"オブジェクトへの参照を持ちます。したがって、あなたの "プライベート"変数はa.getValue.func_closure[0].cell_contents.testとしてアクセス可能です。 (getValueだけでなく、ラップされた関数を使用して "プライベート"オブジェクトにすることもできます。)一般的に、この種の手法は、コードを使用している他のプログラマーを悩ませることになります。

10

のpython:これをしないでください。

There is no need to make things truly private in Python。ソフトウェアを使用している人は、何かがプライベート(変数名は_で始まる)とマークされているかどうかを知ることができます。彼らがまだそれにアクセスしたいのであれば、なぜそれらを止めるのですか?

あなたのコードの周りにも道があると確信しています - Pythonは信じられないほどの内省的なコードを持っており、クラスの変更は簡単です。誰かが実際にそれにアクセスしたい場合、何かをロックすることは事実上不可能です。

また、Pythonではsetters/gettersは無意味です。目的は、属性の設定/取得に関するコードを追加できるようにすることです。これはPythonでthe property() builtinを使用して行うことができます。

4

特にオリジナルのソースを読んでいる場合は、Pythonのものを手に入れる方法があります。 kindallの例を使用して、ファイルの末尾に次の行を追加してください。

実際には、この手順を実行しないでください。 Pythonの人々は、「私的変数を気にしないでください」という理由があります。

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

を、それがプライベートvaribleへのアクセスを得るために作業の多くを取るので、それをやった人はリスクを知っているのに十分知っている必要があります。したがって、あなたが_attributeプライベート属性を使用しているプログラマがいる場合、あなたが投稿した解決策は、プライベート属性を使いこなす前に、それについて考えるように効果的になります。 __attribute(ダブルアンダースコア)を使用すると、名前のマングリングが発生します。これは、「プライベート」属性にアクセスすることを決定する前に、人々がもう少し考えを行うのと同じ効果があります。

編集:Accessing private membersの2番目の回答によれば、C++標準ではクラス内のメンバー変数の順序が保証されていないため、あなたが望むプライベート変数に少しでもアクセスしなければならないかもしれません。上記のC++の例。

関連する問題