04 类&属性的补充
文章目录
类相关补充
1.元类(type):
- 创建类对象的类
2.类对象的创建方式:
- 用class创建
- 自己手动创建,调用type()
3.类的创建流程:
- 检测类中是否明确__metaclass__属性
- 检测父类中是否存在__metaclass__属性
- 检测模块中是否存在__metaclass__属性
- 通过内置的type这个元类来创建这个类对象
4.元类的应用场景:
- 拦截类的创建
- 修改类
- 返回修改之后的类
5.经典类与新式类
- 经典类:没有继承(object)
- 新式类:继承(object)
- python2定义类时,默认不继承;python3定义类时默认继承
- 推荐使用新式类
注: __bases__可以查看其父类
属性相关补充
0. 实例属性的访问顺序:
- 实例对象自身的__dict__字典
- 对应类对象的__dict__字典
- 如果有父类,再往上层检测
- 如果没找到,又定义了__getattr__方法,就会调用这个方法
1. 私有化属性
- python没有真正的私有化支持,但是可以通过使用下划线完成伪私有的效果 [属性和方法遵循同样的规则]
- 公有属性:
- 类内部访问
- 子类内部访问
- 模块其他位置访问
- 跨模块访问(用import导入)
- 受保护属性:加一条下划线 _y
- 类内部和子类内部访问都不会有问题
- 类访问和实例访问也可以访问,但是会有警告
- 跨模块访问
- import形式 —— 可访问但被警告
- from module import * :指明变量警告,没有指明就报错
- 私有属性:加两条下划线 __z
- 类内部可以访问,子类内部不可以访问
- 模块内其他位置都不可以访问
- 跨模块访问,参考上面
- 实现机制:
- 名字重整:自动重改__x为另一个名称,如:_类名__x,可以通过__dict__查看
- 目的:防止外界直接访问,防止被子类同名属性覆盖
- 通常通过类内部的__int__方法初始化,私有化属性只能在类内部直接更改,外部引用属性直接更改的并不是该属性的值。
注意:xx_常用语于与系统内置的关键字作区分;
__xx__一般是系统内置的一些写法
2. 只读属性
一个属性(通常是实例属性),只能读取,不能写入
- 方法1:
- 先通过“属性前置双下划线”
私有化
属性 - 再通过公开的方法,允许读取属性
- 先通过“属性前置双下划线”
- 方法2:
- 依然是私有化属性
- 利用
@property
装饰器,以使用属性的方式,来使用读取的方法 - 此时在给这个属性赋值,就会报错
- 另一种方式,如代码示例2
代码示例1: 新式类与property
class Person(object):
def __init__(self):
self.__age = 18
@property
def age(self):
return self.__age
@age.setter
def age(self,value):
self.__age = value
#调用方式
p = Person()
p.age #返回这个值
p.age = 18 #已默认调用设置属性了
代码示例2:__setattr__
class Person:
# 这个方法会在 给一个实例的属性更改值或者添加属性时调用
# 在这个方法内部,才会真正把,该属性和对应数据存储到__dict__字典中
# 所以我们尝试重写这个方法,来达到属性只读的目的,避免给属性改值,或者添加重名新属性
def __setattr__(self,key,value):
if key == "只读属性" and key in self.__dict__.keys():
print("error")
else:
self.__dict__[key] = value
3. 内置特殊属性
- 类属性:
- __dict__: 类的属性
- __bases__: 类的所有父类构成元组
- __doc__: 类的文档字符串
- __name__: 类名
- __module__: 类定义所在的模块
- 实例属性:
- __dict__: 实例的属性
- __class__: 实例对应的类