2012-04-28 32 views
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() 
+5

爲什麼要經歷所有這些麻煩使這個*私人*?這個概念在Python中沒有太多意義... – ChristopheD 2012-04-28 16:03:02

+5

這段代碼很可怕:( – 2012-04-28 16:03:30

+5

在旁註 - 不要使用niceDecorator,使用'functools.wraps()'。 – 2012-04-28 16:07:05

回答

9

這是一個有趣的想法,但是您用於裝飾器的包裝函數將在其func_closure屬性中引用「私人」對象。所以你的「私人」變量可以作爲a.getValue.func_closure[0].cell_contents.test訪問。 (您可以使用任何包裝函數來獲取您的「私人」對象,而不僅僅是getValue。)

通常,這種技術只會讓其他使用您的代碼的程序員惱火。

10

簡而言之:別這樣。

There is no need to make things truly private in Python。使用你的軟件的人可以看到某些東西是否被標記爲私人(變量名稱以_開頭),所以他們知道。如果他們仍然想訪問它,爲什麼要阻止它們?我敢肯定,你的代碼也有一個解決方法 - Python擁有難以置信的內省代碼,修改類很容易。如果有人真的希望得到它,鎖定任何東西實際上是不可能的。

還值得一提的是,在Python中,setter/getters毫無意義。目的是允許您添加代碼來設置/獲取屬性,python允許您使用the property() builtin

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人們說,「不要打擾私有變量」。

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中的第二個答案,C++標準並不保證類中成員變量的順序,所以您可能需要嘗試一點點才能訪問所需的私有變量上面的C++示例。