单元6 类的定义与使用 课件(共61张PPT)-《Python程序设计》同步教学(人民邮电版)

资源下载
  1. 二一教育资源

单元6 类的定义与使用 课件(共61张PPT)-《Python程序设计》同步教学(人民邮电版)

资源简介

(共61张PPT)
单元6
类的定义与使用
Python程序设计
知识入门
知识要点
1.Python 3 面向对象技术简介 2.Python 身份运算符
1.Python 3 面向对象技术简介
(1)类(Class)
在Python 中,类是一个抽象概念,例如学生、职工、教师、学校、班级、图书、电子产品、手机、电视机、西装等客观实体都可以在程序中定义为对应的类,在类中,可以定义每个对象共有的属性和方法,类是用来描述具有相同的属性和方法的对象的集合。
(2)实例化
(3)对象
创建一个类的实例,即创建类的具体对象,也称为实例化。
对象是事物存在的实体,类定义完成后就会产生一个类对象。对类进行实例化操作,创建一个类的实例,就会产生类的实例对象,实例对象是根据类的模板生成的一个内存实体,有确定的数据与内存地址。
1.Python 3 面向对象技术简介
(4)数据成员
类主要包括两类数据成员:属性和方法。类定义了集合中每个对象共有的属性和方法。在类的声明中,属性是用变量来表示的,方法是指在类中定义的函数。
(5)类属性
(6)实例属性
实例属性用来描述根据类创建的实例对象,通过实例属性或者self 变量可以给实例绑定属性。实例属性是指定义在方法内部的属性,通常在类的__init__() 方法内部定义,在各自实例对象的内存中都保存一份,只能通过实例名称而不能通过类名称访问实例属性。也可以通过实例名称修改实例属性值。
描述类的属性称为类属性,它属于类。如果类本身需要绑定一个属性,可以直接在类中定义属性,这种属性是类属性,归类所有。类属性在内存中只有一份,所有实例对象公用,类的所有实例都可以访问。
1.Python 3 面向对象技术简介
(7)方法
方法是指类中定义的函数,通常也分为实例方法和类方法。实例方法是在类中使用def关键字定义的函数,至少有一个参数,一般以名为“self ”的变量作为参数(使用其他名称也可以),而且需要作为第一个参数,实例方法一般使用实例名称调用。类方法是属于类的方法,这种方法要使用@classmethod 来修饰,其第一个参数一般命名为cls(也可以是别的名称)。类方法一般使用类名称调用。
(8)继承
(9)方法重写
如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(Override),也称为方法的重写。
继承是指派生类(Derived Class)继承父类(Base Class)的属性和方法,允许把一个派生类的对象作为一个父类对象。
2.Python 身份运算符
运算符 说明 实例
is is是判断两个标识符是不是引用自同一个对象 x is y,类似id(x) == id(y)。如果引用的是同一个对象则返回True,否则返回False
is not is not是判断两个标识符是不是引用自不同对象 x is not y,类似id(a) != id(b)。如果引用的不是同一个对象则返回结果True,否则返回False。
【说明】表6-1 中的id() 函数用于获取对象的内存地址。
is 与== 的区别是:is 用于判断两个变量的引用对象是否为同一个,== 用于判断引用变量的值是否相等。
循序渐进
知识要点
6.1 创建类及其对象 6.1.2 创建类的实例 6.2 类属性与实例属性 6.3 类方法与实例方法 6.3.1 类的实例方法 6.3.2 类方法 6.3.3 静态方法6 【任务6-1】定义商品类及其成员 【任务6-2】修改与访问类属性、创建实例属性 【任务6-3】定义与访问类的实例方法
6.4 类的构造方法与析构方法
6.4.1 类的构造方法
6.4.2 类的析构方法
6.5 类的继承与方法重写
6.5.1 类的继承
6.5.2 方法继承
6.5.3 方法重写
6.6 Python 3的命名空间和作用域
6.1.1 定义类
在Python 中,类的定义使用class 关键字来实现,定义类的基本语法格式如下。
class ClassName:
# 类体
其中,ClassName 用于指定类名称,一般使用大写字母开头,如果类名称中包括多个单词,后面的几个单词的首字母也要大写,即采用大驼峰法命名,这是类的命名惯例,应遵守;statement 表示类体,类体主要包括类属性定义和方法定义。如果在定义类时,暂时不需要编写代码,也可以在类体中直接使用pass 语句代替实际的代码。
【注意】类名称后有个冒号,类体要向右边合理缩进。
6.1.2 创建类的实例
类定义完成后,并不会真正创建一个实例对象,还需要手动创建类的实例,即实例化类。类的实例化也称为创建对象,其基本语法格式如下。
ClassName(parameterlist)
其中,ClassName 是必选名称,用于指定具体的类名称;parameterlist 是可选参数,当创建一个类时没有创建__init__() 方法,或者当__init__() 方法中只有一个self 参数时,parameterlist 允许省略。
6.1.2 创建类的实例
【实例6-1】演示Python 类的定义与类实例的创建
实例6-1 的代码如下所示。
实例6-1 代码的运行结果如下。
循序渐进
知识要点
6.1 创建类及其对象 6.1.2 创建类的实例 6.2 类属性与实例属性 6.3 类方法与实例方法 6.3.1 类的实例方法 6.3.2 类方法 6.3.3 静态方法6 【任务6-1】定义商品类及其成员 【任务6-2】修改与访问类属性、创建实例属性 【任务6-3】定义与访问类的实例方法
6.4 类的构造方法与析构方法
6.4.1 类的构造方法
6.4.2 类的析构方法
6.5 类的继承与方法重写
6.5.1 类的继承
6.5.2 方法继承
6.5.3 方法重写
6.6 Python 3的命名空间和作用域
6.2 类属性与实例属性
类的成员包括属性和方法,在类中创建了类的成员后,可以通过类的实例进行访问。
在类中定义的变量称为类的属性,根据定义位置的不同,属性可以分为类属性和实例属性。
类实例化后,可以使用其属性,实际上,创建一个类之后,就可以通过类名称访问其属性。
类属性是指在类中的方法外定义的属性,包括公有属性、保护属性和私有属性,类属性可以在类的所有实例之间共享,也就是在所有实例化的对象中公用。
实例属性在方法内定义,通常在类的__init__() 方法中定义,实例属性只属于类的实例,只能通过实例名称访问。
6.2 类属性与实例属性
【实例6-2】演示Python 类的定义与类属性的定义
实例6-2 的代码如下所示。
实例6-2 代码的运行结果如下。
6.2 类属性与实例属性
实例6-2 中的属性style、model、clothingLength、bust、waistline、leeveLength、shoulderWidth都属于Suit 类的属性,这些属性在类中的方法外面、方法内部、类外部都可以访问,但访问形式有区别,如表所示。
访问位置 访问形式与要求 样例
类内部 方法外部 属性名称 style
类内部 方法内部 类名称.属性名称 Suit.bust、Suit.model
self.属性名称 self.style
类外部 类名称.属性名称 Suit.bust
类实例名称.属性名称 suit1.model
由表6-2 可知,类属性的访问形式有4 种:属性名称、类名称. 属性名称、self. 属性名称、类实例名称. 属性名称。
6.2 类属性与实例属性
因为类属性可以在类的所有实例之间共享,如果在类外对类属性进行修改,所有类实例的属性也会同步修改,类属性的值通过多个类实例访问时,其结果相同。
suit2=Suit()
Suit.bust=60.5
print("Suit 类的属性bust 值为:", Suit.bust)
print("suit1 实例的属性bust 值为:", suit1.bust)
print("suit2 实例的属性bust 值为:", suit2.bust)
在实例6-2 中添加以下代码。
新增代码的运行结果如下。
Suit 类的属性bust 值为: 60.5
suit1 实例的属性bust 值为: 60.5
suit2 实例的属性bust 值为: 60.5
从运行结果可以看出,通过3 种方式(Suit.bust、suit1.bust、suit2.bust)访问类属性,其结果均为修改后的属性值。
如前所述,衬衫设计图相当于类,其属性值修改后,所有根据修改后的设计图制作的衬衫实物,其属性值会同步变化。
6.2 类属性与实例属性
suit2.bust=59.5
print("Suit 类的属性bust 值为:", Suit.bust)
print("suit1 实例的属性bust 值为:", suit1.bust)
print("suit2 实例的属性bust 值为:", suit2.bust)
在实例6-2 中添加以下代码。
第2 次新增代码的运行结果如下。
Suit 类的属性bust 值为: 60.5
suit1 实例的属性bust 值为: 60.5
suit2 实例的属性bust 值为: 59.5
从第2 次新增代码的运行结果可以看出,通过类实例suit2 修改bust 属性值后,只有类实例suit2 的bust 属性值发生了变化,而类Suit 的bust 属性值和另一个类实例suit1 的bust属性值都没有改变。这里修改的bust 属性是类实例suit2 的属性,而不是类Suit 的属性。
根据以上分析可知,实例属性也可以通过实例名称进行修改,与类属性不同,通过实例名称修改实例属性后,并不影响类属性和其他实例中相应的实例属性的值,影响的只有实例自身的属性值。
循序渐进
知识要点
6.1 创建类及其对象 6.1.2 创建类的实例 6.2 类属性与实例属性 6.3 类方法与实例方法 6.3.1 类的实例方法 6.3.2 类方法 6.3.3 静态方法6 【任务6-1】定义商品类及其成员 【任务6-2】修改与访问类属性、创建实例属性 【任务6-3】定义与访问类的实例方法
6.4 类的构造方法与析构方法
6.4.1 类的构造方法
6.4.2 类的析构方法
6.5 类的继承与方法重写
6.5.1 类的继承
6.5.2 方法继承
6.5.3 方法重写
6.6 Python 3的命名空间和作用域
6.3.1 类的实例方法
创建类的实例方法的基本语法格式如下。
def functionName( self , parameterlist )
< 方法体>
functionName 表示方法名称,采用小驼峰法命名,使用小写字母开头。self 为必要参数,表示类的实例,可以通过它来传递实例的属性和方法,也可以通过它传递类的属性和方法,其名称self 并不是规定的名称,而是使用Python 编程时的惯用名称,该名称也可以自定义,例如使用this,但是最好还是按照惯例使用self。
parameterlist 用于指定除self 参数以外的参数,各参数之间使用半角逗号“,”进行分隔。
方法体的代码用于实现所需的功能。
6.3.1 类的实例方法
类的实例方法创建完成后,在类外部可以通过类的实例名称和点“.”操作符进行访问,其基本语法格式如下。
instanceName.functionName( parameterValue )
instanceName 表示类的实例名称;functionName 表示要调用的方法名称。
parameterValue 表示调用方法时的实际参数,其个数与创建类的实例方法中parameterlist 的个数相同。
6.3.1 类的实例方法
【实例6-3】演示Python 类的实例方法的定义
实例5-1 的代码如下所示。
实例5-2 代码的运行结果如下。
【说明】
该运行结果为作者运行程序的输出结果,年份不同该结果有变化。
6.3.1 类的实例方法
从实例6-3 可以看出方法__calculateAge() 的名称由两个下划线开头,表明该方法为类的私有方法,只能在类的内部调用,不能在类的外部调用。在类内部调用实例方法的基本语法格式如下。
self.__methodName()
例如:self.__calculateAge()。
在类外部可以调用类的公有方法,调用形式有以下两种。
形式一:类实例名称. 实例方法名称( [ 参数值列表] )。
例如:man.getAge()。
通过实例名称man 调用getAge() 方法时,将实例对象man 自身作为第1 个参数传递给方法的参数self。
形式二:类名称. 实例方法名称( 类实例名称 [, 参数值列表] )。
例如:Person.getAge(man)。
通过类名称Person 调用getAge() 方法时,也需要将实例对象man 自身作为参数传递给方法的参数self。
6.3.2 类方法
在Python 类的内部,使用def 关键字可以定义属于类的方法,这种方法需要使用@classmethod 来修饰,而且第1 个参数一般命名为cls(这只是Python 的惯用名称,也可以使用自定义名称,例如my)。类方法一般使用类的名称来调用,调用时会把类名称传递给类的第1 个参数cls,通过cls 来传递类的属性和方法,但不能传递实例的属性和方法。
实例对象和类对象都可以调用类方法,调用类方法的基本语法格式如下。
形式一:类实例名称. 类方法名称( [ 参数列表] )。
形式二:类名称. 类方法名称( [ 参数列表] )。
【注意】调用类方法与调用类的实例方法有所不同,使用类名称调用类方法时,并不需要将类实例名称作为参数显式传递给类方法。
6.3.3 静态方法
在Python 类的内部,还可以定义静态方法,这种静态方法需要使用@staticmethod 来修饰,静态方法没有self 和cls 参数,方法体中不能使用类或实例的任何属性和方法。
实例对象和类对象都可以调用类的静态方法,要访问类的静态方法,可以采用类名称调用,并且不会向静态方法传递任何参数。
调用类的静态方法的基本语法格式如下。
形式一:类实例名称. 类静态方法名称()。
形式二:类名称. 类静态方法名称()。
静态方法是类中的函数,不需要实例。静态方法在逻辑上属于类,但是和类本身没有关系,也就是说静态方法中不会涉及类中的属性和方法的操作。可以理解为,静态方法是个独立的、单纯的函数,仅仅托管于某个类的名称空间中,便于使用和维护。
定义商品类及其成员
【任务6-1】
【任务描述】
(1)在PyCharm 中创建项目“Unit06”。
(2)在项目“Unit06”中创建Python 程序文件“t6-1.py”。
(3)定义商品类Commodity。
(4)定义类的多个公有属性和私有属性。
(5)定义多个实例方法。
(6)分别通过类名称、实例名称访问类的属性。
(7)分别通过类的实例方法输出类的公有属性和私有属性值。
【任务6-1】
01
【任务实施】
02
成功启动PyCharm 后,在指定位置“D:\PycharmProject\”创建PyCharm 项目“Unit06”。
在PyCharm 项目“Unit06”中,新建Python 程序文件“t6-1.py”,PyCharm 窗口中显示程序文件“t6-1.py”的代码编辑区域,在该程序文件的代码编辑区域中自动添加了模板内容。
03
在文件“t6-1.py”的代码编辑区域中的已有模板注释内容下面输入代码,程序文件“t6-1.py”中类定义的代码如下所示。
【任务6-1】
【任务实施】
04
针对创建的类Commodity 实施以下各项操作。
(1)直接使用类名称访问类的公有属性。
(2)使用类的实例名称访问类的公有属性
(3)调用类的实例方法输出类的公有属性
【任务6-1】
【任务实施】
04
针对创建的类Commodity 实施以下各项操作。
(4)通过类名称或类的实例名称访问类的私有属性
(5)调用类的实例方法输出类的私有属性
修改与访问类属性、创建实例属性
【任务6-2】
【任务描述】
(1)在项目“Unit06”中创建Python 程序文件“t6-2.py”。
(2)创建类Commodity 并定义其属性和方法。
(3)创建类对象goods1 和goods2。
(4)通过类名称Commodity 调用类的实例方法,输出类初始定义的公有属性。
(5)使用类名称Commodity 修改类的公有属性。
(6)直接使用类名称Commodity 输出类修改之后的公有属性。
(7)使用类实例名称goods1 输出类修改之后的公有属性。
(8)使用类实例名称goods2 输出类修改之后的公有属性。
(9)通过类名称Commodity 调用类的实例方法,输出类修改之后的公有属性。
(10)通过类实例名称goods1 调用类的实例方法,输出类修改之后的公有属性。
(11)第2 次修改类的公有属性。
(12)直接使用类名称Commodity 输出类第2 次修改之后的公有属性。
(13)使用类实例名称goods1 输出类第2 次修改之后的公有属性。
(14)使用类实例名称goods2 输出类第2 次修改之后的公有属性。
(15)通过类名称Commodity 调用类的实例方法,输出类第2 次修改之后的公有属性。
(16)分别通过类实例名称goods1、goods2 调用类的实例方法,输出类第2 次修改之后的公有属性。
【任务6-2】
01
【任务实施】
在PyCharm 项目“Unit06”中,新建Python 程序文件“t6-2.py”,在该程序文件“t6-2.py”的代码编辑区域中创建类Commodity 并定义其属性和方法的代码详见“t6-1.py”对应的代码。
【任务6-2】
02
【任务实施】
针对创建的类Commodity 进行类属性、实例属性的修改与访问。
(1)创建类对象
(2)通过类名称Commodity 调用类的实例方法,输出类初始定义的公有属性。
(3)使用类名称Commodity 修改类的公有属性。
【任务6-2】
02
【任务实施】
针对创建的类Commodity 进行类属性、实例属性的修改与访问。
(4)直接使用类名称Commodity 输出类修改之后的公有属性。
(5)使用类实例名称goods1 输出类修改之后的公有属性。
(6)使用类实例名称goods2 输出类修改之后的公有属性。
【任务6-2】
02
【任务实施】
针对创建的类Commodity 进行类属性、实例属性的修改与访问。
(7)通过类名称Commodity 调用类的实例方法,输出类修改之后的公有属性。
(8)通过类实例名称goods1 调用类的实例方法,输出类修改之后的公有属性。
(9)第2 次修改类的公有属性。
【任务6-2】
02
【任务实施】
针对创建的类Commodity 进行类属性、实例属性的修改与访问。
(10)直接使用类名称Commodity 输出类第2 次修改之后的公有属性。
(11)使用类实例名称goods1 输出类第2 次修改之后的公有属性。
(12)使用类实例名称goods2 输出类第2 次修改之后的公有属性。
【任务6-2】
02
【任务实施】
针对创建的类Commodity 进行类属性、实例属性的修改与访问。
(13)通过类名称Commodity 调用类的实例方法,输出类第2 次修改之后的公有属性。
(14)分别通过类实例名称goods1、goods2 调用类的实例方法,输出类第2 次修改之后的公有属性。
运行结果之一 运行结果之二 运行结果之三
定义与访问类的实例方法
【任务6-3】
【任务描述】
(1)在项目“Unit06”中创建Python 程序文件“t6-3.py”。
(2)在程序文件“t6-3.py”中创建类对象goods。
(3)在程序文件“t6-3.py”中调用多个类的实例方法,输出所需数据。
【任务6-3】
01
【任务实施】
在PyCharm 项目“Unit06”中创建Python 程序文件“t6-3.py”。在程序文件“t6-3.py”中编写代码,实现所需功能。创建类Commodity 并定义私有属性、实例方法的代码如下所示。
【任务6-3】
02
【任务实施】
针对创建的类Commodity 实施以下各项操作。
(1)创建类对象goods。
(2)调用多个类的实例方法,输出所需数据。
程序文件“t6-3.py”的运行结果如下所示。
循序渐进
知识要点
6.1 创建类及其对象 6.1.2 创建类的实例 6.2 类属性与实例属性 6.3 类方法与实例方法 6.3.1 类的实例方法 6.3.2 类方法 6.3.3 静态方法6 【任务6-1】定义商品类及其成员 【任务6-2】修改与访问类属性、创建实例属性 【任务6-3】定义与访问类的实例方法
6.4 类的构造方法与析构方法
6.4.1 类的构造方法
6.4.2 类的析构方法
6.5 类的继承与方法重写
6.5.1 类的继承
6.5.2 方法继承
6.5.3 方法重写
6.6 Python 3的命名空间和作用域
6.4.1 类的构造方法
在Python 中,类有一个名为“__init__”的特殊方法,称为构造方法,该方法在类实例化时会自动调用,不需要显式调用。
【说明】“__init__”是Python 默认的方法名称,其开头和结尾处是两个下划线(下划线中间没有空格)。
在创建类时,类通常会自动创建一个__init__() 方法,每当创建一个新的类实例时,如果用户没有重新定义构造方法,则系统自动执行默认的构造方法__init__(),进行一些初始化操作。对于如下代码,实例化类Person 时,对应的__init__() 方法就会被调用。
man = Person ()
6.4.1 类的构造方法
【实例6-4】演示Python 类的构造方法定义
实例6-4 的代码如下所示。
运行结果
姓名: 李明
性别: 男
年龄: 19
6.4.2 类的析构方法
在Python 中,析构方法的基本语法格式为:__del__(self)。在释放对象时系统自动调用
该方法,不需要显式调用,可以在该方法中编写代码,进行一些释放资源的操作。
循序渐进
知识要点
6.1 创建类及其对象 6.1.2 创建类的实例 6.2 类属性与实例属性 6.3 类方法与实例方法 6.3.1 类的实例方法 6.3.2 类方法 6.3.3 静态方法6 【任务6-1】定义商品类及其成员 【任务6-2】修改与访问类属性、创建实例属性 【任务6-3】定义与访问类的实例方法
6.4 类的构造方法与析构方法
6.4.1 类的构造方法
6.4.2 类的析构方法
6.5 类的继承与方法重写
6.5.1 类的继承
6.5.2 方法继承
6.5.3 方法重写
6.6 Python 3的命名空间和作用域
6.5.1 类的继承
1.单一继承
Python 支持类的继承,子类的定义如下所示。
class DerivedClassName( ParentClassName ):
< 类体>
其中,DerivedClassName 用于指定子类名称;ParentClassName 用于指定要继承的父类名称,可以有多个,对于单一继承只有一个。如果不指定父类名称,则继承Python 的基类object。类体为实现所需功能的代码,包括属性、方法的定义,如果定义类时暂时无须编写代码,可以直接使用pass 语句代替。
父类ParentClassName 必须与子类定义在一个作用域内。
6.5.1 类的继承
【实例6-5】演示Python 类和单一继承子类的定义
实例6-5 的代码如下所示。
运行结果
父类Person 的属性name 值为: 李明
父类Person 的属性sex 值为: 男
子类Student 的属性name 值为: 李明
子类Student 的属性sex 值为: 男
子类Student 的属性grade 值为: 95
6.5.1 类的继承
2.多重继承
Python 在一定程序上支持多继承形式。多继承的类定义基本语法格式如下。
class DerivedClassName( ParentClassName1, ParentClassName2,… ):

需要注意小括号中父类的顺序,若父类中有相同的方法名,而子类在使用时未指定继承
自哪个父类,Python 将从左至右搜索括号中的父类。
DerivedClassName 用于指定子类名称,ParentClassName1、ParentClassName2……
则表示继承的多个父类名称,使用半角逗号“,”分隔。
6.5.2 方法继承
子类可以继承父类的实例方法,也可以增加自己的实例方法。子类对象可以直接调用父类的实例方法,调用的基本语法格式如下。
子类名称. 父类方法名称( [ 参数列表] )
例如member.printTest()。
6.5.3 方法重写
父类的成员都会被子类继承,如果程序中的父类方法的功能不能满足需求,可以在子类重写父类中的同名方法,子类可以覆盖父类中的任何方法,子类的方法中也可以调用父类中的同名方法。
循序渐进
知识要点
6.1 创建类及其对象 6.1.2 创建类的实例 6.2 类属性与实例属性 6.3 类方法与实例方法 6.3.1 类的实例方法 6.3.2 类方法 6.3.3 静态方法6 【任务6-1】定义商品类及其成员 【任务6-2】修改与访问类属性、创建实例属性 【任务6-3】定义与访问类的实例方法
6.4 类的构造方法与析构方法
6.4.1 类的构造方法
6.4.2 类的析构方法
6.5 类的继承与方法重写
6.5.1 类的继承
6.5.2 方法继承
6.5.3 方法重写
6.6 Python 3的命名空间和作用域
6.6 Python 3 的命名空间和作用域
在理解Python 的命名空间和作用域前,先看一下计算机中的多个磁盘、多个文件夹与多个文件的存储关系。
计算机中可以有多个硬盘,同一个硬盘中可以有多个逻辑分区(即磁盘),同一个磁盘中可以有多个文件夹,同一个文件夹中可以有多个文件。并且同一个磁盘中不能出现重名的文件夹,同一文件夹中不能出现重名的文件,但不同磁盘或不同文件夹中的文件可以重名。
x01.txt
02.txt
02.txt
y01.txt
文件夹x
文件夹y
磁盘E:
文件夹x
磁盘F:
x01.txt
y01.txt
6.6 Python 3 的命名空间和作用域
Python 的命名空间提供了在项目中避免名称冲突的一种方法。各个命名空间是独立的,没有任何关系,所以虽然一个命名空间中不能有重名,但不同的命名空间是可以有重名的。
Python 的命名空间结构主要由包、模块、类、函数、方法、属性、变量组成,相同的对象名称可以存在于多个命名空间中。
一个Python 项目中可以定义多个包,并且包名要不同,例如“package01”“package02”;一个包中可创建多个模块,同一个包中的多个模块名称要不同,不同包的模块可以重名;一个模块中可以定义多个类、函数、变量,同一个包的同一个模块中定义的类、函数、变量的名称要不同,不同的包或同一个包的不同模块中定义的类、函数、变量可以重名;一个类中可以定义多个属性、方法,同一个类中的多个属性、方法名称要不同,不同名称的类或不同级别的类(父类与子类)中定义的属性、方法可以重名;一个函数中可以定义多个变量,同一个函数中的多个变量名称要不同,不同函数中定义的变量可以重名。
6.6 Python 3 的命名空间和作用域
Python 的命名空间结构如图所示。
package01
module01
ClassA
ClassB

methodX
attributeM
attributeN
methodX
attributeM
attributeN

methodX
attributeM
attributeN

functionX
functionY
module02
variableM
variableN
variableM
variableN
module01
package02
ClassA

ClassB

methodX
attributeM
attributeN

methodX
attributeM
attributeN

项目N
1.3 种命名空间
(1)内置命名空间(Built-in Namespace)
Python 内置的名称,例如函数名abs、char 和异常名称BaseException、Exception 等。
(2)全局命名空间(Global Namespace)。
全局名称指模块中定义的名称,记录了模块级变量,包括函数、类、其他导入的模块级的变量和常量。
(3)局部命名空间(Local Namespace)
局部名称指函数中定义的名称,记录了函数级变量,包括函数的参数和局部定义的变量。类内以及类的方法中定义的名称也属于局部名称。
2.命名空间的查找顺序
假设要使用变量var,则Python 的查找顺序为:局部命名空间→全局命名空间→内置命名空间。
如果找不到变量var,它将放弃查找并引发NameError异常。运行结果如下。
NameError: name 'var' is not defined
3.命名空间的生命周期
命名空间的生命周期取决于对象的作用域,如果对象执行完成,则相应命名空间的生命周期结束。因此,我们无法从外部命名空间访问内部命名空间的对象。示例如下。
#var1 是全局名称
var1 = 5
def local_func():
#var2 是局部名称
var2 = 6
def inner_func():
# var3 是内置的局部名称
var3 = 7
4.作用域
在Python 中,程序的变量并不是在任何位置都可以访问的,访问权限取决于这个变量是在哪里赋值的。变量的作用域决定了哪一部分程序可以访问哪些特定的变量。Python 的作用域一共有4 种,具体如下。
局部作用域(L,Local):最内层,包含局部变量,例如一个函数或方法内部。
闭包函数外的函数(E,Enclosing):包含非局部(Non-Local)、非全局(Non-Global)的变量;例如两个嵌套函数,一个函数(或类)A 里面又包含一个函数B,那么对于B 中的名称来说A 的作用域就为Non-Local。
全局作用域(G,Global):当前程序的最外层,例如当前模块的全局变量。
内置作用域(B,Built-in):包含内置的变量、关键字等,最后才被搜索。
4.作用域
Python 查找的规则顺序为:L → E → G → B。即在局部作用域找不到,便会去局部作用域外的局部找(例如闭包函数外的函数),如果没找到就会去全局作用域查找,最后去内置作用域中查找。
示例如下。
g_count = 1 # 全局作用域
def outer():
o_count = 2 # 闭包函数外的函数中
def inner():
i_count = 3 # 局部作用域
4.作用域
内置作用域是通过一个名为builtins 的标准模块来实现的,但是这个变量名并没有放入内置作用域内,所以必须导入这个模块才能够使用它。在Python 3.0 中,可以使用以下的代码来查看builtins 模块中预定义了哪些变量。
>>>import builtins
>>>dir(builtins)
在Python 中,只有模块、类以及函数才会引入新的作用域,其他的代码块(例如try…except、if…elif…else、for…while 等)是不会引入新的作用域的,也就是说这些语句内定义的变量,在其外部也可以访问,示例代码如下。
>>>if True:
msg = 'I wish you good health.'
>>> msg
'I wish you good health.'
4.作用域
以上代码中msg 变量定义在if 语句块中,但在其外部也可以访问msg 变量。
如果将msg 定义在函数中,则它就是局部变量,在其外部不能访问,示例如下。
>>>def printInfo():
msg_inner = 'I wish you good health.'
>>>msg_inner
运行以上代码时会出现如下异常信息。
Traceback (most recent call last):
File "", line 1, in
NameError: name 'msg_inner' is not defined
从以上异常信息可以看出,msg_inner 未定义,无法使用,因为它是局部变量,只有在函数内可以使用。
5.全局变量和局部变量
定义在函数内部的变量拥有局部作用域,定义在函数外的变量拥有全局作用域。
局部变量只能在其被定义的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内定义的变量名称都将被加入作用域中。
【实例6-6】演示Python 的全局变量和局部变量的定义与使用
实例6-6 的代码如下所示。
函数内是局部变量: 26.0
函数外是全局变量: 0
运行结果
6.关键字global 和nonlocal
当在内部作用域想修改外部作用域的变量时,就要用到global 关键字。在函数内部,既可以使用global 关键字来声明使用外部全局变量,也可以使用global 关键字直接定义全局变量。
【实例6-7】演示在函数内定义与修改全局变量num
实例6-7 的代码如下所示。
函数内部1 : 2
函数内部2 : 5
函数外部1 : 5
函数外部2 : 8
运行结果
THANKS

展开更多......

收起↑

资源预览