Области действия переменных в классах Python

#python #oop #scope

#python #ооп #область видимости

Вопрос:

Объявление переменной в классе (вне функции): все функции класса могут получить к ней доступ (в основном, к общедоступной переменной)

Объявление переменной внутри функции внутри класса: только эта функция может получить к ней доступ (она находится в области видимости этой функции)

Объявление переменной с self.(variable name) внутренней функцией внутри класса: все функции класса могут получить к ней доступ (чем это отличается от global (variable name) ?)

И поскольку не существует частных / защищенных, все является общедоступным, поэтому все, что доступно изнутри класса, доступно и снаружи класса.

Есть ли какие-либо другие нюансы, которые я должен знать, или я в значительной степени понял это?

Комментарии:

1. Но в принципе, да, у ypu по умолчанию в Python нет таких вещей, как «частные» переменные (я говорю «по умолчанию», потому что можно использовать некоторую магию самоанализа, чтобы иметь поведение, подобное приватному / защищенному). Итак, зачем вам нужны частные переменные? Соглашение заключается в том, что методы / атрибуты, имя которых начинается с одного «_», не являются общедоступными и не должны быть изменены извне объекта. Идея частных переменных для запутывания / безопасности ошибочна по своей природе.

Ответ №1:

Поскольку список в вашем вопросе не на 100% понятен, я решил объяснить это на простом примере. Он также включает некоторые вещи, такие как __something переменные, которые вы не упомянули в своем списке.

 class Test:
    a = None
    b = None

    def __init__(self, a):
        print self.a
        self.a = a
        self._x = 123
        self.__y = 123
        b = 'meow'
  

В начале, a и b являются только переменными, определенными для самого класса — доступными через Test.a и Test.b и не специфичными для какого-либо экземпляра.

При создании экземпляра этого класса (что приводит к __init__ выполнению):

  • print self.a не находит переменную экземпляра и, таким образом, возвращает переменную класса
  • self.a = a : создается новая переменная экземпляра a . Это затеняет переменную класса, поэтому self.a теперь будет ссылаться на переменную экземпляра; для доступа к переменной класса теперь вам нужно использовать Test.a
  • Присвоение self._x создает новую переменную экземпляра. Это считается «не частью общедоступного API» (он же защищенный), но технически его поведение ничем не отличается.
  • Присвоение self.__y создает новую переменную экземпляра с именем _Test__y , т. Е. ее имя искажено, поэтому, если вы не используете искаженное имя, к ней нельзя получить доступ извне класса. Это может быть использовано для «частных» переменных.
  • Присвоение b создает локальную переменную. Она недоступна ни из чего, кроме __init__ функции, поскольку не сохраняется в экземпляре, классе или глобальной области видимости.

Комментарии:

1. Есть ли причина, по которой вы не используете Test(object) ? Итак, ваш ответ также применим к классам нового типа ?

2. @DavorJosipovic есть такая штука, которая называется Python3.

3. если мы вызываем класс следующим образом: ** obj = Test(«name») **, то этот объект является экземпляром или object . что это за объект на самом деле.

4. Кроме того, аргумент a in __init__(self, a) является локальной переменной только внутри __init__ .

Ответ №2:

Объявление переменной на верхнем уровне класса похоже на объявление статической переменной или переменной класса. Присвоение ему значения self означает объявление переменной экземпляра. Переменные класса могут быть изменены путем ссылки на них по имени класса (например, Class.x = 5 ), и все экземпляры унаследуют эти изменения. Переменные экземпляра являются частными для экземпляра и могут быть изменены только этим экземпляром.

Вы можете достичь некоторого уровня контроля доступа, используя символы подчеркивания. Смотрите Частные переменные в руководстве по Python. По соглашению, переменные, начинающиеся с одного подчеркивания, например, _foo , являются непубличными частями API, а имена, начинающиеся с двух подчеркиваний, например, __foo , будут изменены на _classname__foo .

Ответ №3:

Несмотря на ответы, позвольте мне добавить несколько комментариев к вашим вопросам:

Объявление переменной в классе (вне функции): все функции класса могут получить к ней доступ (в основном, к общедоступной переменной)

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

Объявление переменной внутри функции внутри класса: только эта функция может получить к ней доступ (она находится в области видимости этой функции):

Если переменная объявлена без self , то она доступна только внутри этой функции, как локальная переменная. Однако, если она была объявлена с использованием self like self.var= 'somevalue' , то она доступна через любой объект, но не через имя класса.

Объявление переменной с self.(variable name) внутренней функцией внутри класса : все функции класса могут получить к ней доступ (чем это отличается от global (variable name) ?)

Смотрите ответ в приведенной выше части.

И поскольку не существует частного / защищенного, все является общедоступным, поэтому все, что доступно изнутри класса, доступно и снаружи класса

Да, но мы можем использовать один символ подчеркивания, чтобы сообщить миру, что эта переменная является частной, но технически это фактически не делает ее частной.

Ответ №4:

мы можем использовать область видимости в этом случае как: случай 1: В классе

 class test:
     def __init__(self, a):
          self.__elements = a
     def change_a(self): self.__elements = 5
  

случай 2: Внешний класс

 t = test(5)
  

Доступ к ним будет осуществляться как к объекту._classname__privatevaribalename

 print(t._test__elements)
  

при этом будет выведено измененное значение