1 .类相关补充
1.1 元类
- 概念:创建类对象的类
对象由类产生,而类也是一个对象,所以类对象是由另外一个类产生出来的,这个类就是元类

1.2 类对象的创建方式
- 利用type()函数 / 元类
type有两个作用:
第一个作用是直接输入对象,便可调出该对象的数据类型
第二个作用就是作为元类创建类对象
- 语法: 变量名 = type(类名str,父类tuple,方法属性dict)
类名:存储在类中的类的名称,为字符串,若不指定,需传入空字符串:“ ”
父类:新创建的类可以继承父类的一些特点(属性、方法等)
以元组形式传入,若没有父类要传入空元组:(),默认继承object
绑定的方法属性:需要以字典键值对形式传入
变量名:只起调用类的作用,可以与类名相同,调用时应输入变量名,而不是类名
- 元类的查找机制 / 类创建流程
在用type创建类时,
- 会先在自身通过__metaclass__属性查找是否有指定元类,若有则通过这个元类来创建
- 若没有,再检测父类中是否存在__metaclass__属性
- 若没有,再检测模块中是否存在__metaclass__属性
- 若以上三者均不存在,则通过内置的type元类来创建新的类对象

1.3 元类的应用场景(作用)
- 拦截类的创建
- 修改类
- 返回修改之后的类
1.4 类的描述(注释)
- 注释的作用
在创建了类之后,添加相应的注释,可以方便我们去理清整个模块的思路
- 描述方式(类似函数)
直接在类或者方法的下面,使用三个双引号 """ """ 跨行书写,规范如下:
class Person:
"""
这里写关于这个类的描述,类的作用,类的构造函数;
以及类属性的描述
Attributes:
count:写这个属性的含义,类型...
"""
count = 1
def run(self,distance,step):
"""
写这个方法的作用效果
:param distance:代表距离,int类型,是否有默认值...
:param step: 代表步长,int类型...
:return: 返回结果的含义,返回的数据类型...
"""
print("你好")
return distance / step
help(Person)
2.属性相关补充
2.1 私有化属性 / 变量
私有化属性是指将一些原本公开的属性设置权限, 只能小范围访问(如:只能在类的内部访问), 其他地方访问不了
其作用主要是为了保护数据的安全性,提高代码的可维护性
2.1.1 访问权限测试区域划分
在给出具体私有化属性之前,我们先界定一下各个访问区域的位置
通常,我们分为 类的内部、子类内部、模块内部的其他位置、模块外部(跨模块)四个区域

2.1.2 三种属性类型
属性类型 | 定义方式 | 备注 |
---|---|---|
公有属性 x | 变量名 = xxx (与常规属性定义一样) | |
受保护属性 _y | _ 变量名 = xxx 一个下划线 | |
私有属性 __z | __ 变量名 = xxx 两个下划线 | 必须在类的内部定义才有效,在实例等定义无效 |
class Animal:
x = 100 # 公有属性
_y = 200 # 受保护属性
__z = 300 # 私有属性
pass
print(Animal.x)
print(Animal._y)
print(Animal.__z)
2.1.3 三种属性类型的访问权限
首先在某个类中定义一个属性,然后测试在不同区域的访问权限
访问区域 | 公有属性 | 受保护属性 | 私有属性 |
---|---|---|---|
类的内部 | √ | √ | √ |
子类内部 | √ | √ | × |
模块内其他位置 | √ | √(但会提醒) | × |
模块外部 (跨模块) | √(两种方式) import形式导入 | √(但会提醒) import形式导入 第二种方式需要先写 __all__ = ["变量"] | 同受保护属性 |
2.1.4 私有属性的实现机制及应用
Python并没有真正的私有化支持,但是, 可以使用下划线完成伪私有的效果
- 具体实现机制:名字重整
使用__x,解释器会自动帮我们冲改成另一个名称:_ 类名 __x
所以再次访问时,会访问不到 __x;如果想访问,需要访问 _ 类名 __x
- 应用场景:数据保护、数据过滤
class Person:
"""
这个类的好处是:会默认年龄为18,设定age为私有属性,对数据进行了保护
同时又可以通过两个函数在实例中对age进行修改和访问
"""
def __init__(self):
"""
__init__主要作用:当我们创建好一个实例化对象之后,会自动调用这个方法,来初始化这个对象
好处:如果是在类中定义,则在每个实例中都不能修改,这样定义,则可以修改
"""
self.__age = 18
def setAge(self, value): # 用来修改年龄
self.__age = value
def getAge(self): # 用来获取年龄
return self.__age
p1 = Person()
p1.setAge(20)
print(p1.getAge())
p2 = Person()
print(p2.getAge())
2.1.5 变量添加下划线的其他补充
- xx_ :"变量名_" 这个格式是为了与系统属性作区分
- __xx__:两端__ 一般为系统内置属性或方法, 所以以后命名注意避免
2.2 只读属性
只读属性是指只能读取、不能写入的(实例)属性,例如:电脑的网速,网络状态
2.2.1 实现方式一:私有化 + 部分公开
class Person:
def __init__(self):
self.__age = 18 # 私有化
def getAge(self): # 用来公开:读取
return self.__age
p1 = Person()
print(p1.getAge())
- 问题:1)和传统直接调用函数名读取的方式不一致,读取的方式发生了变化
2)当我们直接调用函数名读取时,不会报错,而是会新增一个属性
- 优化:使用@property装饰器装饰函数
property的作用:可以将属性的 删 改 查 这三个操作关联到不同的方法里
class Person(object): #,如果要设置只读属性,应先继承object类
def __init__(self):
self.__age = 18 # 私有化
#这里的作用是,可以以使用属性的方式,来读取这个方法
@property
def age(self): # 用来公开:读取
return self.__age
p1 = Person()
print(p1.age)
p1.age = 20
2.2.2 经典类和新式类以及property的应用
- 经典类:没有继承object类 Python2.x版本定义一个类时, 默认不继承(object)
- 新式类:继承了object类 Python3.x版本定义一个类时, 默认继承(object)
- 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
@age.deleter #删除
def age(self):
del self.__age
p1 = Person()
print(p1.age)
p1.age = 20
print(p1.__dict__)
del p1.age
print(p1.__dict__)
2.2.3 实现方式二:借助系统内置的方法__setattr__进行拦截
因为方式一中,是通过伪私有的方式进行私有化属性,我们依然可以通过 _ 类名 __x 的方式访问属性,所以这种方法存在一定的风险
class Person:
def __setattr__(self, key, value):
"""
当我么通过 实例.属性 = 值,给实例增加或修改属性时,都会调用这个方法
在这个方法内部,才会真正的把这个属性以及对应的数据,存储到__dict__字典中
"""
print(key, value)
# 1. 判定, key, 是否是我们要设置的只读属性的名称
if key == "age" and key in self.__dict__.keys():
print("这个属性是只读属性, 不能设置数据")
# 2. 如果说不是, 只读属性的名称, 真正的给它添加到这个实例里面去
else:
# self.key = value
self.__dict__[key] = value
p1 = Person()
p1.age = 18
# p1.name = "sz"
# print(p1.age)
print(p1.age)
p1.age = 999
print(p1.age)
print(p1.__dict__)
2.3 内置特殊属性
内置属性 | 作用 | 备注 |
---|---|---|
__dict__ | 查看类 / 对象的属性 | 类属性 |
__bases__ | 类的所有父类构成元组 | |
__doc__ | 类的文档字符串 | |
__name__ | 类名 | |
__module__ | 类定义所在的模块 | |
__class__ | 实例对应的类 | 实例(对象)属性 |
3.方法相关补充
3.1 私有化方法
类似于私有化属性,私有化方法是指将一些原本公开的方法设置权限, 只能小范围访问
- 语法:def __方法(): 两个下划线
pass
这个方法原理与私有化属性一样,也是名字重制,要想调用需要输入 "_类名__方法名"
3.2 内置特殊方法(了解即可)
分为生命周期方法(下一章讲)和其他内置方法
内置方法 | 作用 | 格式 | 触发方式 |
---|---|---|---|
__str__ | 直接输出return后面的描述信息,面向用户,方便阅读 | def __str__(self): | print(实例)或 str(实例) |
__repr__ | 直接输出return后面的描述信息,面向开发人员,方便维护 | def __repr__(self): | repr(实例) |
__call__ | 使得“对象”具备当做函数,来调用的能力,调用__call__ 方法下我们定义的内容 | def __call__(self): xxxx调用内容 | 对象名() (不需要用.__call__) |
__setitem__ 增 __getitem__ 查 __delitem__ 删 | 可以对一个实例对象像字典一样进行索引操作 | def __setitem__(self, key, value): 另外两个同理 | p["xxx"] = "xx" p["xxx"] del p["xxx"] |
__iter__ 优先级高__getitem__ ...低 | 可以让我们自己创建的对象使用for in 进行遍历,并返回方法对应的数据 | for in 遍历 | |
__next__ | 让对象可以使用next函数进行访问 | next(对象) |