Область видимости переменных класса Python?

#python #python-2.7

#python #python-2.7

Вопрос:

Я изучаю Python (мое образование — C, C ).

В следующем коде из tutorialspoint.com:

 class Employee:
   'Common base class for all employees'
   empCount = 0

   def __init__(self, name, salary):
      self.name = name
      self.salary = salary
      Employee.empCount  = 1
   
   def displayCount(self):
     print "Total Employee %d" % Employee.empCount

   def displayEmployee(self):
      print "Name : ", self.name,  ", Salary: ", self.salary

"This would create first object of Employee class"
emp1 = Employee("Zara", 2000)
"This would create second object of Employee class"
emp2 = Employee("Manni", 5000)
emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount
  

(1) Моя путаница заключается в переменных экземпляра ‘self.name «, самооценка.зарплата». Я понимаю, что переменные в Pythons не нуждаются в явном объявлении, в отличие от C, но тогда как эти переменные могут использоваться в методе ‘displayEmployee’, разве у них нет собственной локальной области видимости, которая является методом конструктора ‘_ init _’? Кроме того, эта переменная ‘self’ является объектом для создаваемого класса — так что это будет означать, что объявление класса в Python также создает объект этого класса (поэтому никаких виртуальных классов, как в C ) одновременно?

(2) Мой второй (менее важный) вопрос, в приведенном выше коде, почему случайно размещенные строки «Это создаст первый объект класса Employee» и «Это создаст второй объект класса Employee», не показывают ошибку? Насколько я знаю, комментарии должны начинаться с # или «‘? Или строки также рассматриваются как пробелы в Python?

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

1. Подождите, вы используете python 2?

2. Да, sry должен был упомянуть, что

3. Это конец срока службы, поэтому, вероятно , не стоит изучать / использовать намного дольше. Хотя у Python3 был бы тот же ответ

4. self как this в C

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

Ответ №1:

  1. Создание объекта (т.е. Emplyee() Вызывает __init__() метод, инициализатор). Все методы, которые затем имеют self аргумент, используют экземпляр этого объекта для работы. Это означает, что эти методы будут иметь доступ к self переменным этого объекта. Это означает, что статические методы не имеют к этому доступа, и почему доступ к этим переменным экземпляра не приводит к ошибке. В качестве примера, это приведет к ошибке:
 class Employee:
    def __init__(self):
        self.variable = 123

    @staticmethod # Decorator to indicate this method should not accept 'self'
    def static_method():
        print(self.variable)
  

Потому что метод static_method() не работает с инициализирующим экземпляром Employee объекта.

  1. Строки, как и любая другая неназначенная переменная, будут интерпретироваться, а затем отбрасываться. Например, следующее:
 123
"test"
[1, 2]
  

Все они ничего не делают, но, учитывая, что они являются технически корректными утверждениями, они не приводят к ошибкам. Вы часто будете видеть этот тип инструкций в docstrings, например:

 """
Long string goes here.
"""
  

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

1. Стоит упомянуть строки в тройных кавычках для документации.

2. Итак, переменные self — все ли они обязательно определены в init, или некоторые другие методы также могут определять переменные для self?

3. Инициализатор — это инициализатор. Новый — это конструктор. New должен каждый раз возвращать новый экземпляр, init можно использовать для повторной инициализации столько раз, сколько вы хотите. type.__call__ это то, что на самом деле гарантирует, что оба будут вызваны, когда вы это сделаете Employee()

4. Переменные экземпляра не обязательно определять в конструкторе класса / объекта. Лучше всего, чтобы вы могли получить лучшее «представление» о том, какие методы экземпляра существуют в классе, просто взглянув на конструктор, и вы избежите потенциального столкновения с an AttributeError при ссылке на переменные экземпляра, которые еще не определены. Однако любой метод экземпляра может создавать новые переменные экземпляра, если вы решите это сделать.

5. Отличная мысль @MadPhysicist — исправлено. @Kaind, (i) Это правильно. Попытка получить доступ к переменной экземпляра (атрибуту), которая не существует AttributeError , вызовет displayCount() , который присваивает / создает эту переменную, затем остановит это поведение (в вашем случае). (ii) В этом нет необходимости, но использование self чаще встречается, чем нет. Подумайте о классе, который имеет некоторую функцию, которая не взаимодействует ни с одним из атрибутов / переменных экземпляра этого класса, вы можете сделать этот метод статическим и удалить в self качестве первого аргумента.