Python "защищенные" атрибуты - PullRequest
       33

Python "защищенные" атрибуты

34 голосов
/ 28 апреля 2009

Как получить доступ к закрытому атрибуту родительского класса из подкласса (не делая его общедоступным)?

Ответы [ 7 ]

81 голосов
/ 28 апреля 2009

Я понимаю соглашение Python

  • _правитель защищен
  • __ участник приватен

Параметры, если вы контролируете родительский класс

  • Сделать его защищенным, а не частным так как это похоже на то, что вы на самом деле хочет
  • Использовать геттер (@property def _protected_access_to_member ...) для ограничения защищенного доступа

Если вы не контролируете это

  • Отмените искажение имени. если ты dir (объект) вы увидите имена что-то вроде _Class__member, который является что Python делает, чтобы привести __ к «сделай это частным». Нет действительно частный в питоне. Это, вероятно, считается злом.
39 голосов
/ 19 января 2014

Две философии защиты

Некоторые разработчики языка придерживаются следующего предположения:

«Многие программисты безответственны, глупы или оба».

Эти дизайнеры языка будут испытывать желание защитить программистов друг от друга, введя спецификатор private в их язык. Вскоре они признают, что это часто слишком негибко, и вводят protected.

Разработчики языка, такие как Гвидо ван Россум из Python, напротив, предполагают, что программисты ответственные взрослые и способны на здравое суждение (возможно, не всегда, но обычно). Они считают, что каждый должен иметь доступ к элементам программы, если это необходимо, чтобы язык не мешал делать правильные вещи. (Единственный язык программирования, который может надежно помешать сделать неправильный , - это NULL язык)

Следовательно, _myfield в Python означает что-то вроде: «Разработчик этого модуля делает некоторые неочевидные вещи с этим атрибутом, поэтому, пожалуйста, не изменяйте его и не читайте его, если можете - подходящими способами для доступа к соответствующей информации были предоставлены (или так мы надеемся). "

Если вы не можете избежать доступа к _myfield (например, в особых случаях в подклассе), вы просто получаете к нему доступ.

15 голосов
/ 16 апреля 2011

Используя @property и @name.setter, чтобы делать то, что вы хотите

* 1005 например *

class Stock(object):

    def __init__(self, stockName):

        # '_' is just a convention and does nothing
        self.__stockName  = stockName   # private now


    @property # when you do Stock.name, it will call this function
    def name(self):
        return self.__stockName

    @name.setter # when you do Stock.name = x, it will call this function
    def name(self, name):
        self.__stockName = name

if __name__ == "__main__":
      myStock = Stock("stock111")

      myStock.__stockName  # It is private. You can't access it.

      #Now you can myStock.name
      N = float(raw_input("input to your stock: " + str(myStock.name)+" ? "))
2 голосов
/ 27 августа 2017

Кажется, никто не отвечает на первоначальный вопрос

как получить доступ к закрытому атрибуту родительского класса из подкласса

Итак, вот простой пример использования, демонстрирующий два варианта - доступ к родительскому классу __ приватным переменным и использование @ property decorator :

class Family:

    def __init__(self, name):
        self.__family_name = name

    @property
    def name(self):
        return self.__family_name


class Child(Family):

    def __init__(self, first_name, last_name):
        super(Child, self).__init__(last_name)
        self.__child_name = first_name


    @property
    def name(self):
        return (self.__child_name, super(Child, self).name)


if __name__ == '__main__':
    my_child = Child("Albert", "Einstein")

    # print (my_child.__child_name)         # AttributeError - trying to access private attribute '__child_name'
    # print (my_child.__family_name)        # AttributeError - trying to access private attribute '__family_name'
    print (my_child._Child__child_name)     # Prints "Albert" - By accessing __child_name of Child sub-class
    print (my_child._Family__family_name)   # Prints "Einstein" - By accessing __family_name in Family super-class
    print (" ".join(my_child.name))         # Prints "Albert Einstein" - By using @property decorators in Child and Family 
2 голосов
/ 28 апреля 2009

если имя переменной «__secret» и имя класса «MyClass», вы можете получить к нему доступ таким образом в экземпляре с именем «var»

var._MyClass__secret

Соглашение о том, чтобы предлагать / подражать защите, состоит в том, чтобы называть ее символом подчеркивания: self._protected_variable = 10

Конечно, любой может изменить его, если он действительно хочет.

0 голосов
/ 22 октября 2017

Я думаю, что этот код немного яснее, чем код Стива. Ответ Стива был самым полезным для того, что я пытаюсь сделать, так что спасибо! Я протестировал это с python 2.7 и python 3.6.

#! /usr/bin/python
#
# From /628780/python-zaschischennye-atributy
from __future__ import print_function
import sys

class Stock(object):

    def __init__(self, stockName):

        # '_' is just a convention and does nothing
        self.__stockName  = stockName   # private now


    @property # when you do Stock.name, it will call this function
    def name(self):
        print("In the getter, __stockName is %s" % self.__stockName, file=sys.stderr)
        return self.__stockName

    @name.setter # when you do Stock.name = x, it will call this function
    def name(self, name):
        print("In the setter, name is %s will become %s" % ( self.__stockName, name), file=sys.stderr)
        self.__stockName = name

if __name__ == "__main__":
    myStock = Stock("stock111")

    try:
        myStock.__stockName  # It is private. You can't access it.
    except AttributeError as a:
        print("As expect, raised AttributeError", str(a), file=sys.stderr )
    else:
        print("myStock.__stockName did did *not* raise an AttributeError exception")


    #Now you can myStock.name
    myStock.name = "Murphy"
    N = float(input("input to your stock: " + str(myStock.name)+" ? "))
    print("The value of %s is %s" % (myStock.name, N) )
0 голосов
/ 28 апреля 2009

Сделайте метод доступа, если я что-то упустил:

def get_private_attrib(self):
  return self.__privateWhatever
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...