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

#matplotlib #pyqt5

#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») **, то этот объект является экземпляром или объектом. что это за объект.

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

Ответ №2:

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

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

Ответ №3:

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

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

объявление переменной внутри функции внутри класса: только эта функция может получить к ней доступ (в этой области функций): комментарий: если переменная объявлена без self, то она доступна только в этой функции, своего рода локальной переменной. Однако, если он объявлен с использованием self, например self.var= ‘somevalue’,, то он доступен через любой объект, но не через имя класса.

объявление переменной с помощью self .(имя переменной) внутри функции внутри класса: все функции класса могут получить к ней доступ (чем это отличается от глобального (имя переменной)?): комментарий: см. asnswer в приведенной выше части.

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

Ответ №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)
 

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