Python 中对象的属性分为实例属性、类属性、私有属性、特殊属性、装饰器属性 (property) 五大类,同时区分实例访问、类访问、继承行为,下面逐一拆解。
一、类属性(Class Attribute)
定义在 class 内部、方法外部,属于类本身,所有实例共享同一份数据。
特点
classPerson:
species ="人类"# 类属性
p1 = Person()
p2 = Person()
print(Person.species)# 类直接访问:人类
print(p1.species)# 实例访问:人类
# 类修改,全部实例同步变化
Person.species ="智人"
print(p2.species)# 智人
# 实例赋值,创建独立实例属性,不再共用
p1.species ="男人"
print(p1.species)# 男人(实例属性)
print(Person.species)# 智人(类属性不变)
二、实例属性(Instance Attribute)
绑定在单个对象上,仅当前实例独有,定义两种方式:
__init__
classPerson:
def__init__(self, name):
self.name = name # 实例属性
p = Person("张三")
p.age =20# 动态新增实例属性
print(p.name, p.age)
# print(Person.name) 报错:类没有实例属性
三、私有属性(约定式私有,无真严格私有)
Python 没有语法级私有,靠命名规范区分访问权限:
1. _xxx 单下划线:保护属性(protected)
约定:仅类内部、子类使用,外部不建议直接访问,语法上仍可读取。
classPerson:
def__init__(self):
self._id =1001# 保护属性
p = Person()
print(p._id)# 能访问,但不推荐
2. __xxx 双下划线:名称改写(name mangling)
底层自动改名 _类名__属性,外部无法直接通过 obj.__xxx 访问,模拟私有。
classPerson:
def__init__(self):
self.__password ="123456"
p = Person()
# print(p.__password) # AttributeError 报错
print(p._Person__password)# 强制绕过,不建议使用
3. xxx_ 尾下划线
仅用来规避和 Python 关键字重名,无私有含义:
cls_ ="学生"# class是关键字,加下划线区分
四、property 装饰器:可控属性(读写校验属性)
普通属性无法限制赋值,@property 将方法伪装成属性,支持读、改、删,适合数据校验。
1. 只读属性(仅 getter)
classPerson:
def__init__(self, age):
self._age = age
@property
defage(self):
# 获取时自动执行逻辑
return self._age
p = Person(18)
print(p.age)# 像属性一样调用,不加()
# p.age = 20 报错,无setter不能修改
2. 可读可写(getter + setter)
classPerson:
def__init__(self, age):
self._age = age
@property
defage(self):
return self._age
@age.setter
defage(self, val):
# 赋值校验
ifnotisinstance(val,int):
raise ValueError("年龄必须整数")
if0< val <150:
self._age = val
else:
raise ValueError("年龄超出范围")
p = Person(18)
p.age =25
print(p.age)
# p.age = 200 抛异常
3. 删除属性 deleter
@age.deleter
defage(self):
del self._age
del p.age
五、特殊内置属性(魔术属性)
每个类 / 实例自带系统内置属性,前后双下划线 __xxx__:
__dict__:字典,存储当前对象所有自定义属性p = Person(18)
print(p.__dict__)# {'_age': 18}
print(Person.__dict__)# 类属性、方法
__class__:返回实例所属类
print(p.__class__)# <class '__main__.Person'>
__name____bases____doc__
六、补充:动态属性相关工具
1. __slots__ 限制允许的实例属性
默认实例用 __dict__ 存属性,内存开销大;__slots__ 固定属性列表,禁止动态新增属性,节省内存。
classPerson:
__slots__ =["name","age"]# 仅允许这两个实例属性
def__init__(self, n, a):
self.name = n
self.age = a
p = Person("李四",22)
# p.gender = "男" 报错,不允许新增属性
2. getattr / setattr / delattr 动态操作属性
p = Person("王五",20)
print(getattr(p,"name"))# 获取属性
setattr(p,"age",21)# 修改属性
delattr(p,"age")# 删除属性
七、各类属性对比总结