python中的类变量

python中的类变量,python,class,variables,static,Python,Class,Variables,Static,我(无意中)编写了以下代码: #!/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:

我(无意中)编写了以下代码:

#!/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
变量虽然已声明为类(静态)变量,但其行为不作为类(静态)变量

2) 即使在从方法中访问
balance
变量时使用
self
关键字阻止了静态行为,在哪一点上创建了类变量
balance
的实例副本?(至少这就是我所推断的,每个对象都有自己的副本-,应该是类变量-
balance

3) 通过反复试验,我发现获得(预期?)行为的一种方法是使用@classmethod注释方法。这是不是像Java中的s.th一样阻止从非静态方法访问静态变量

我知道和帖子,但我认为它们没有解决上述问题。

诀窍在于:

self.balance -= amount
这实际上意味着:

self.balance = self.balance - amount
现在,复杂的事情是,
self.balance
在任务的任何一边实际上都不是一回事。首先对RHS进行评估:Python尝试查找实例变量,失败后返回到类变量。但是现在它做LHS,这里它只是做它通常做的事情:直接赋值给一个名为
balance
的实例变量

关键是LHS不知道原始值来自类变量;它只是将它被告知的位置分配给
self.balance
,这是一个实例变量

当然,从那时起,实例变量就存在了,因此对
self.balance
的任何进一步读取都将得到该变量,而不是原始的类变量:类变量保持不变,但被实例变量隐藏

将方法定义为classmethod时,第一个参数不再是实例(self),而是类本身;出于这个原因,习惯上调用该参数
cls
。因此,您可以直接读写类变量。

诀窍在于:

self.balance -= amount
这实际上意味着:

self.balance = self.balance - amount
现在,复杂的事情是,
self.balance
在任务的任何一边实际上都不是一回事。首先对RHS进行评估:Python尝试查找实例变量,失败后返回到类变量。但是现在它做LHS,这里它只是做它通常做的事情:直接赋值给一个名为
balance
的实例变量

关键是LHS不知道原始值来自类变量;它只是将它被告知的位置分配给
self.balance
,这是一个实例变量

当然,从那时起,实例变量就存在了,因此对
self.balance
的任何进一步读取都将得到该变量,而不是原始的类变量:类变量保持不变,但被实例变量隐藏


将方法定义为classmethod时,第一个参数不再是实例(self),而是类本身;出于这个原因,习惯上调用该参数
cls
。因此,您可以直接读写类变量。

如果我能够如此优雅地表达它,我会说的正是这些。如果将
self.balance
替换为
Account.balance
,那么它的行为将与预期的OP一样。可能提到类变量仍然存在,只是在
self.checkBalance
方法中没有引用它。因此,当python无法找到实例变量
self.x
时,它返回到查找类变量
x
?在这种情况下,实际发生在比较
if amount>self.balance
中。在语句前面加上减量运算符。另外:
@classmethod
注释是否阻止创建实例变量,尽管存在
self.
?注释是否指示解释器忽略(包括)
之前的任何内容?嗯,它在任何地方都会这样做,但有趣的是我在赋值语句中描述的事情。不,关键是你在classmethod中调用的不是self而是cls:它是类,不是实例。不要忘记,
self
cls
只是约定,你可以使用你喜欢的任何名称,但最好清楚的是,在classmethod的情况下,第一个参数是class对象。如果我能如此优雅地表达它,我会这么说的。如果将
self.balance
替换为
Account.balance
,那么它的行为将与预期的OP一样。可能提到类变量仍然存在,只是在
self.checkBalance
方法中没有引用它。因此,当python无法找到实例变量
self.x
时,它返回到查找类变量
x
?在这种情况下,实际发生在比较
if amount>self.balance
中。在语句前面加上减量运算符。另外:
@classmethod
注释是否阻止创建实例变量,尽管存在
self.
?注释是否指示解释器忽略(包括)
之前的任何内容?嗯,它在任何地方都会这样做,但有趣的是我在赋值语句中描述的事情。不,关键是你在classmethod中调用的不是self而是cls:它是类,不是实例。不要忘记,
self
cls
只是约定,您可以使用任何您喜欢的名称,但最好清楚的是,对于classmethod,第一个参数是class对象。