类是属性和方法的集合,创建新类就是创建新的对象类型。
名称和对象
对象是类的实例化,对象之间相互独立,但不同作用域下的不同名称可以绑定到同一个对象
命名空间和作用域
命名空间
命名空间是从名称到对象的映射,大部分命名空间都是通过Python字典来实现的。命名空间内不能有重名,但是不同命名空间可以重名而没有任何影响,注意区分模块
- 内置名称 > 全局名称 > 局部名称
内置名称
- python解释器启动时创建,永远不会被删除
例如,ads、char、BaseException、Exception等全局名称
- 读取模块定义时创建,持续到解析器退出
局部名称
- 调用函数时创建,在函数返回或抛出不在函数内部处理的错误时被删除
作用域
命名空间可直接访问的 Python 程序的文本区域
python中访问变量,会从内到外,依次访问所有作用域直到找到,否则报错未定义
- 顺序:局部作用域Local → (外部嵌套作用域Enclosing)→ 全局作用域Global → 内置模块作用域Built-in
- 只有模块、类、函数才会引入新的作用域,其他代码块内定义的变量,外部也可以访问
# if中声明的变量a,外部仍可访问
if 1 > 0:
a = 1
print("a =", a)
# 输出结果 a = 1
全局变量
- 将引用和赋值直接指向包含该模块的全局名称命名空间
- 调用函数时,所有函数内声明的名称都会加到作用域中
局部变量
- 仅在被声明的函数内访问
关键字
global,局部作用域影响到全局作用域
a = 1
def fun():
global a
print(a) # 结果为1
a = 2
print(a) # 结果为2
fun()
print(a) # global声明后结果为2,否则为1
nonlocal,嵌套作用域影响到局部作用域
def outer():
a = 1
def inner():
nonlocal a
print(a) # 结果为1
a = 2
print(a) # 结果为2
inner()
print(a)# nonlocal声明后结果为2,否则为1
outer()
类
类声明
class ClassName:
<statement-1>
.
<statement-N>
开始声明类时,将创建一个新的命名空间,作为局部作用域,类声明完成时,将创建一个类对象
类对象
class MyClass:
"""A simple example class"""
i = 12345
def f(self):
return 'hello world'
属性引用
语法:
obj.name
,有效的属性名称是类对象被创建时存在于类命名空间中的所有名称
例:Myclass.i,Myclass.f
实例化
示例:
x=Myclass()
,可以把类对象视为是返回该类的一个新实例的不带参数的函数
实例化会创建一个空对象,通常会自动调用__init()__方法进行初始化,
def __init__(self):
self.data = []
实例对象
x=Myclass()
的x
是实例对象
实例对象可进行属性引用,两种有效的属性名称:数据属性和方法,实例对象的有效方法名称依赖于其所属的类
方法对象
x.f
是方法对象,可以被保存后再调用
调用x.f()时没有带参,这是因为方法所属实例对象会作为函数的第一个参数被传入,调用x.f()就相当于调用Myclass.f(x)
xf = x.f
while True:
print(xf())
官方文档解释: 当一个实例的非数据属性被引用时,将搜索实例所属的类。 如果被引用的属性名称表示一个有效的类属性中的函数对象,会通过打包(指向)查找到的实例对象和函数对象到一个抽象对象的方式来创建方法对象:这个抽象对象就是方法对象。 当附带参数列表调用方法对象时,将基于实例对象和参数列表构建一个新的参数列表,并使用这个新参数列表调用相应的函数对象。
示例
类变量用于所有实例共享,而实例变量是每个实例唯一数据
可迭代对象除外!可变对象如列表、字典,不会被用作类变量,而是所有实例共享一个
将代码改写为以下情况,才可以使得实例唯一
补充
方法的第一个参数名称
self
,没有特殊含义,与普通函数区分开,换成其他名称同样是可正执行的