2012-04-28 6 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

+5

Этот код страшен :( –

+5

На боковой ноте - не используйте 'niceDecorator'. Используйте' functools.wraps() '. –

ответ

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 сеттеры/геттеры бессмысленны. Цель состоит в том, чтобы позволить вам добавлять код при настройке/получении атрибута, который позволяет вам использовать 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 (double-underscore) вызовет некоторое изменение имени, что также имеет тот же эффект, что и люди, которые могут немного подумать, прежде чем принимать решение о доступе к «частным» атрибутам.

Редактировать: Согласно второму ответу в Accessing private members, стандарт C++ не гарантирует порядок переменных-членов в классе, поэтому вам может потребоваться немного поэкспериментировать, чтобы получить доступ к частной переменной, которую вы хотите в Пример C++ выше.

Смежные вопросы