2015-03-27 2 views
0

I (случайно) написал следующий код:Переменные класса в Python

#!/usr/bin/python3.4 

class Account: 

    balance = 1000 

    def withdraw(self, amount): 
     print('Withdrawing') 
     if(amount > self.balance): 
      print("You cannot withdraw that amount!") 
     else: 
      self.balance -= amount 

    def checkBalance(self): 
     if (self.balance == 0): 
      print("Your account is empty.") 
     else: 
      print("You still have ", str(self.balance) + "€ euros in your account!") 


def Main(): 
    account1 = Account() 
    account2 = Account() 

    account1.withdraw(100) 
    account1.withdraw(300) 

    account1.checkBalance() 
    account2.checkBalance() 


if __name__ == "__main__": 
    Main() 

выход:

Withdrawing 
Withdrawing 
You still have 600€ euros in your account! 
You still have 1000€ euros in your account! 

Мои вопросы:

1) почему переменная balance не ведет себя как class (статическая) переменная, хотя она была объявлена ​​как таковая?

2) даже если использование ключевого слова self при доступе к переменной balance изнутри методов предотвращает статическое поведение, в какой момент это экземпляр экземпляра переменной класса balance? (по крайней мере, это то, что я предполагаю, что каждый объект получает свою собственную копию - то, что должно быть переменной класса - balance)

3) методом проб и ошибок я обнаружил, что способ получить (ожидается?) - это аннотировать методы с помощью метода @classmethod. Является ли это s.th, как в Java, который предотвращает доступ статических переменных от нестатических методов?

Я знаю this и this сообщений, но IMHO они не затрагивают вышеуказанные последствия.

ответ

4

Хитрость здесь:

self.balance -= amount 

Это на самом деле переводится:

self.balance = self.balance - amount 

Теперь, сложная вещь, что self.balance на самом деле не то же самое, по обе стороны от этого задания. Сначала проверяется RHS: Python пытается найти переменную экземпляра, терпит неудачу и возвращается к переменной класса. Но теперь он делает LHS, и здесь он просто выполняет то, что обычно выполняет: присваивает непосредственно переменной экземпляра под названием balance.

Дело в том, что LHS не знает, что исходное значение пришло из переменной класса; он просто назначает, где сказано, self.balance, который является экземпляром var.

Конечно с тех пор, экземпляр вар существует, поэтому дальше считывание self.balance получат, что вместо переменной первоначального класса: переменная класса существует без изменений, но слежки переменного экземпляра.

Когда вы определяете метод как метод класса, первый параметр больше не является экземпляром (self), а сам класс; по этой причине принято называть этот аргумент cls. Таким образом, вы читаете и записываете непосредственно в переменную класса.

+0

Именно то, что я сказал бы, если бы мог выразить это так элегантно. Если 'self.balance' были заменены на' Account.balance', тогда он будет вести себя так, как ожидалось OP. – mhawke

+0

, возможно, упоминает, что переменная класса все еще существует, просто она не упоминается в методе 'self.checkBalance'. – will

+0

Итак, когда python не находит переменную экземпляра 'self.x', она возвращается к поиску переменной класса' x'? В этом случае это фактически происходит в сравнении 'if amount> self.balance'. который предшествует утверждению оператором декремента. Также: аннотация '@ classmethod', предотвращающая создание переменной экземпляра DESPITE, существование' self.'?Является ли аннотация инструктированием интерпретатора игнорировать что-либо до (включая) '.'? – pkaramol

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