1.概念

类变量:定义在类中,但是在函数体之外的变量。通常不使用self.变量名赋值的变量。类变量通常不作为类的实例变量,类变量对于所有实例化的对象中是公用的。
实例变量:定义在方法中的变量,使用self绑定到实例上的变量,只是对当前实例起作用。

2.访问

先来看一个代码

class Student():
   name = "Marry Liu"    # 类变量
   age = 0    # 类变量

   def __init__(self, name, age):
         name = name  # 局部变量
         age = age


s = Student('Carrie', 19)
print s.name, s.age
print Student.name, Student.age

print s.__dict__
print Student.__dict__

结果:

Marry Liu 0
Marry Liu 0
{}
{‘age’: 0, ‘module’: ‘main’, ‘name’: ‘Marry Liu’, ‘init’: <function init at 0x7fc02518b668>, ‘doc’: None}

这里我们要说一下实例变量的查找机制:
当在实例变量中查找不到某一变量时候,就会去类变量里查找,当再查找不到的时候就会在父类中查找,因此输出的name为Marry Liu, 而不是Carrie。s的内容之所以为空,是因为我们实例化对象的时候为指明实例变量的保存。

下面更改一下代码:

class Student():
   name = "Marry Liu"  # 类变量
   age = 0  # 类变量

   def __init__(self, name, age):
         self.name = name  # 实例变量
         self.age = age


s = Student('Carrie', 19)
print s.name, s.age
print Student.name, Student.age

print s.__dict__
print Student.__dict__

结果:

Carrie 19
Marry Liu 0
{‘age’: 19, ‘name’: ‘Carrie’}
{‘age’: 0, ‘module’: ‘main’, ‘name’: ‘Marry Liu’, ‘init’: <function init at 0x7f0d73606668>, ‘doc’: None}

我们传入的self只和实例化的对象有关和类无关,代表实例。

访问规则:

  1. 类变量可以通过“类名.类变量名”、“实例名.类变量名”两种方式读取,即类和实例都能读取类变量。
class Student():
   name = "Marry Liu"  # 类变量
   age = 0  # 类变量

   def __init__(self, major):
         self.major = major  # 实例变量


s = Student('Computer Science')
print s.name, s.age
print Student.name, Student.age

print s.__dict__
print Student.__dict__

结果:

Marry Liu 0
Marry Liu 0
{‘major’: ‘Computer Science’}
{‘age’: 0, ‘module’: ‘main’, ‘name’: ‘Marry Liu’, ‘init’: <function init at 0x7f6d4efda668>, ‘doc’: None}

  1. 实例变量只能通过“实例名.实例变量名”的方式访问,类无权访问实例名。
class Student():
   name = "Marry Liu"  # 类变量
   age = 0  # 类变量

   def __init__(self, major):
         self.major = major  # 实例变量


s = Student('Computer Science')
print s.major
print Student.major

print s.__dict__
print Student.__dict__

结果:

Computer Science
Traceback (most recent call last):
File “/home/maqian/Algrithom/JianZhi_offer/ttttt.py”, line 21, in
print Student.major
AttributeError: class Student has no attribute ‘major’

  1. “类名.类变量名”、“实例名.类变量名”访问的实际上是同一个命名空间的变量,所以类变量具有“一改全改”的特点。
class Student():
   name = "Marry Liu"  # 类变量
   age = 0  # 类变量

   def __init__(self, major):
         self.major = major  # 实例变量


s = Student('Computer Science')
print s.name, s.age, s.major
print Student.name, Student.age

print s.__dict__
print Student.__dict__

print "----------------------"
Student.name = 'Penny'
Student.age = 21

print s.name, s.age, s.major
print Student.name, Student.age

print s.__dict__
print Student.__dict__

结果:

Marry Liu 0 Computer Science
Marry Liu 0
{‘major’: ‘Computer Science’}
{‘age’: 0, ‘module’: ‘main’, ‘name’: ‘Marry Liu’, ‘init’: <function init at 0x7f1908e87668>, ‘doc’: None}
----------------------
Penny 21 Computer Science
Penny 21
{‘major’: ‘Computer Science’}
{‘age’: 21, ‘module’: ‘main’, ‘name’: ‘Penny’, ‘init’: <function init at 0x7f1908e87668>, ‘doc’: None}

  1. 采用‘实例名.类变量名’的方式对类变量进行赋值时,若该类变量是可变数据类型,则可以成功赋值该类变量,否则会在该实例变量所在的名称空间中创建一个与该类变量同名的实例变量进行赋值,并不会对类变量进行赋值,此时也无法再通过‘实例名.类变量名’的方式读取该类变量。但若‘实例名.类变量名’赋值的是可变数据类型,则可以对类变量进行赋值操作。
class Student():
   name = "Marry Liu"  # 类变量
   age = 0  # 类变量
   place = ['China', 'Beijing']

   def __init__(self, major, name):
       self.name = name
       self.major = major  # 实例变量


s = Student('Computer Science', 'Lily Liu')
print s.name, s.age, s.place, s.major
print Student.name, Student.age, Student.place
s.place[1] = 'Shanghai'
print s.name, s.age, s.place, s.major
print Student.name, Student.age, Student.pla

结果:

Lily Liu 0 [‘China’, ‘Beijing’] Computer Science
Marry Liu 0 [‘China’, ‘Beijing’]
Lily Liu 0 [‘China’, ‘Shanghai’] Computer Science