类变量【类名.类变量名】
1、类变量在class内,但不在class的任何方法内,存在类的内存里
2、类变量是该类所有实例共享的变量,但是
实例对象只能访问,不可修改
,每个实例对象去访问同一个类变量都将得到相同结果【实例名.类变量名】
3、新增、修改、删除类变量n,不会影响到同名实例变量n
4、类无权访问实例变量
5、类变量可修改、新增、删除
Python类变量被赋值
(1)类的设计里
class里def外,通过变量名能被赋值,如下:w = 10;def里通过类对象即类名字的点运算变量名可被赋值,如下:Test.h = 50
(2)程序里
通过类对象(类名字)的点运算类名字也可被赋值,如下:Test.w = 20 # 通过类名修改类变量
class Test:
w = 10 # 类变量
def __init__(self):
Test.h=50
a = Test()
print (a.w) # 通过实例访问类变量 输出10
a.w = 100 # 类变量并没有修改,而是添加了一个实例变量w,a.w=a.w+100是可以的
print (a.w) # 通过实例访问实例变量,已经屏蔽同名类变量 输出100
Test.w = 20 # 通过类名修改类变量
print (Test.w, Test.h) #输出20 50
Test.t = 15 # 动态添加类变量
print(a.t) # 通过实例访问类变量t
del Test.t # 删除类变量t
实例变量(实例属性)
实例变量(实例属性)【实例名.实例变量名】
1、实例变量是构造函数下的变量带self.变量
2、实例变量为每个实例本身独有,不可相互调用、新增、修改、删除,不可被类调用、新增、修改、删除
3、可以访问类变量
4、如果同时有类变量和实例变量,程序执行时,先访问实例变量,实例变量存在,会使用实例变量,实例变量不存在,会使用类变量
5、实例改类变量,不可修改,实际是在实例内存里创建了实例变量
6、新增、修改、删除实例变量n,不会影响到类变量n
7、a实例不能调用b实例的变量
8、实例变量可修改、新增、删除
Python实例对象变量被赋值
(1)类的设计里
def里通过self点运算变量名能被赋值,不一定非在__init__里,其他已被调用的方法函数里也行
(2)程序里
通过实例对象的点运算变量名可被赋值
>>> class Student: # 类的定义体
classroom = '101' # 类变量
address = 'beijing' # 类变量
def __init__(self, name, age):
self.name = name #实例变量
self.age = age #实例变量
def print_age(self):
print('%s: %s' % (self.name, self.age))
>>> li = Student("李四", 24) # 创建一个实例
>>> zhang = Student("张三", 23) # 创建第二个实例
>>> li.classroom # li本身没有classroom实例变量,所以去寻找类变量,它找到了!
'101'
>>> zhang.classroom # 与li同理
'101'
>>> Student.classroom # 通过类名访问类变量
'101'
>>> li.classroom = '102' # 关键的一步!实际是为li创建了独有的实例变量,只不过名字和类变量一样,都叫做classroom。
>>> li.classroom # 再次访问的时候,访问到的是li自己的实例变量classroom
'102'
>>> zhang.classroom # zhang没有实例变量classroom,依然访问类变量classroom
'101'
>>> Student.classroom # 保持不变
'101'
>>> del li.classroom # 删除了li的实例变量classroom
>>> li.classroom # 一切恢复了原样
'101'
>>> zhang.classroom
'101'
类和实例在内存中的存储
类变量和实例变量的区别:
1、类变量不通过实例化后可直接打印输出,类变量存储在类的内存中,如上图;
2、同样的属性名称同时出现在实例和类中,则属性查找会优先选择实例。
变量访问限制(公有属性和私有属性)
在python中,变量名类似__xxx__,也就是以双下划线开头并且以双下划线结尾的是特殊变量,一般系统使用,特殊变量是可以直接访问的,不是private变量,所以一般不用__name__, __score__这样的变量名。
以一个下划线开头的实例变量名,比如_foo,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。
双下划线开头的实例变量是私有变量,是不是一定不能从外部访问呢?其实也不是。不能直接访问__foo是因为Python解释器对外把__foo变量改成了_类名__foo,所以,仍然可以通过:类(或实例名)._类名__XXX的方式访问。
class Student:
'''
Student类的定义体
Student.__doc__ 访问该部分信息
'''
_classroom = '101' # 类的保护变量
address = 'beijing'
def __init__(self, name, age):
self.name = name # 实例变量
self.age = age
self.__foo__="init" # 实例的私有变量
self.__class="python班级"
def print_age(self):
print('%s: %s' % (self.name, self.age))
print(self.__foo__)
print(self.__class) # 内部可以访问私有变量
s=Student("苏州",20)
s.print_age()
s.__foo__
s._Student__class # 一般外部不访问私有变量,必须访问:类或实例名._类名__XXX; 用s.__dict__查看
Student._classroom # 但下划线 实际上类的外部可以直接访问
print(Student.__doc__) # 查看类的描述信息 , 即类里面注释部分
#---------------------------------------------------------------------------------------
苏州: 20
init
python班级
Student类的定义体
Student.__doc__ 访问该部分信息
系统提供的特殊的属性(内置属性)
property属性可以简化实例对象对属性的操作(获取、设置),可以对属性做类型校验和预处理等。
property属性的创建方式有两种:1、@property装饰器方式 ;2、类属性方式 ( 属性名=property() )
1)、@property的作用是把一个getter方法变成属性,@xxxx.setter把setter方法变成属性赋值,让get和set方法更好用。
2)、property以一个函数形式,定义一个属性,其原型为:property(fget=None, fset=None, fdel=None, doc=None)
class Animal(object):
def __init__(self, name, age ,color):
self._name = name
self._age = age
self._color = color
def get_name(self):
return self._name
def set_name(self, value):
if isinstance(value, str):
self._name = value
else:
self._name = 'No name'
name = property(get_name, set_name, "属性描述信息...") # 类属性方式定义属性
@property # 访问属性值 相当于其他语言的get ;@property装饰器方式
def age(self):
return self._age
@age.setter # 设置属性值 相当于其他语言的set ,可以更好的效验等控制
def age(self, value):
if value > 0 and value < 100:
self._age = value
else:
self._age = 0
print ('invalid age value.')
@property
def color(self):
return self._color
@color.setter
def color(self, value):
self._color = value;
a = Animal('black dog', 3 ,'Black')
a.name = 'white dog'
a.age = 20
print ('Name:', a.name) # Name: white dog
print ('Age:', a.age) # Age: 20
print ('Color:',a.color) # Color: Black