Python 类的学习_1
主要学习内容
- 面向对象概述
- 类的定义和使用
- 属性
- 继承
面向对象概述
面向对象,Object Oriented
,简称 OO
两个核心概念: 对象、类
三个特性:封装、继承、多态
对象
- 属性:静态的,描述性的
- 方法:动态的,有计算、转化等动作的
类
一组相似事物的统称,可以理解为一系列相同的对象的统称。
例如,一个文件夹中有10个文件,其中5个“文本文档1”、“文本文档2” … “文本文档5”,还有5个“工作簿1”、“工作簿2” … “工作簿5”。那么称5个“文本文档”为一个类:“文档类”,5个“工作簿”为一个类“工作簿类”;而每一个文件则称为一个“对象”。
封装、继承、多态(略)
类的定义及创建、使用方法
定义类
主要使用 Class
关键字进行声明,语法如下
Class ClassName: # 类名通常用“驼峰式命名法”
'''帮助信息,对类的说明''' # 注意,应当使用 3引号。
statement # 陈述,说明
# 主要用去定义类的方法、属性
# 如果暂时没有明确的内容定义,也可以用 Pass语句
创建类的实例(对象)
“类的实例” 即是 “对象”,故创建类的实例即为 “创建对象”。语法如下
newObject = ClassName([parameterlist])
# parameterlist,可选参数,根据构造类时是否有定义参数而决定是否为空。
# 具体 ‘类的构造’ 相关方法及内容见后文
parameterlist
参数,如果在创建类的时候没有创建 __init__()
方法,或者 __init__(self)
方法仅有 self
一个参数时,parameterlist
参数可以省略;否则,parameterlist 传递的时 __init__()
方法的参数。
创建 __init__()
方法
init() 是一种构造方法,在创建类的实例(对象)时会自动执行。语法如下:
class ClassName:
def __init__(self[,parameter1,parameter2...]): #定义构造方法
Print("创建了一个ClassName。") # __init__()方法的主体
# 以上创建一个 ClassName 及其构造方法,以下创建一个实例
Object = ClassName([parameter1,parameter2...])
# 运行以上代码,将输出: 创建了一个ClassName。
# 表明在创建实例时,构造方法 __init__() 将会自动运行。
针对以上语法需要说明的是:
__init_(self)
中,必需填写一个参数,可以为任意参数名,通常默认约定写为self
。- 当仅有
self
一个参数时,在创建实例时不需要写参数;否则要输入相应的参数。 - 在创建实例时,构造方法
__init__()
会自动执行。 - 在某些语言(java)中,可以写多个构造方法,通过传递不同的参数构造出不同的对象。在python中,构造方法只能有一个,当出现多个构造方法时,默认识别最后一个构造方法。
示例说明
class Dog:
'''
这里输入类的帮助信息,需要紧跟在类名之后,并用三引号包括
这是一个关于狗的类
'''
def __init__(self,nose,tail): #含有两个参数 鼻子、尾巴
print("创建了一个关于“狗”的类。狗通常有以下特点:")
print(nose) # 鼻子
print(tail) # 尾巴
# -------------- 以上创建一个类及其构造方法,以下实例化一个类
nose_1 = '鼻子很灵敏' #设置两个变量,用于参数赋值
tail_1 = '尾巴略微上翘'
puppy = Dog(nose_1, tail_1) # 创建一个实例 puppy(小狗)
运行以上程序,将返回如下结果
创建了一个关于“狗”的类。狗通常有以下特点:
鼻子很灵敏
尾巴略微上翘
创建类的成员并访问
类的成员主要包括两部分:
- 实例方法,与面向对象的方法相对应
- 数据成员,与面向对象的属性相对应
创建实例方法并访问
实例方法的创建与函数的创建类似,只是其必须有一个 self
参数,语法如下
class ClassName:
def __init__(self[,parameter1,parameter2...]): #定义构造方法
Print("创建了一个ClassName。") # __init__()方法的主体
def FunctionName(self, parameterlist[= DefaultVslur]): # 定义一个方法,并设置了参数的默认值
block # 方法的主体
print('创建了一个方法,其参数为:', parameterlist) # 举例 方法的主体
# self 参数时必需的,但是其参数名并非固定为 self,只是通常约定写作 self
# 以上创建了类的一个 “方法”,以上为使用方法
在创建了实例方法之后,可以通过 类的实例名词和 .
操作符来进行访问,如下
object = ClassName() # 实例化一个对象
object.FunctionName(parameterValue) # 引用对象的方法,其中parameterValue 是调用方法时,自定义的一个参数
示例说明:
class Dog:
def __init__(self): # 定义构造方法
pass # 方法的主体空白
def run(self, state): # 奔跑 方法
print(state)
# -------------- 以上创建一个类及其构造方法,以下实例化一个类
puppy = Dog() # 创建一个实例 puppy(小狗)
puppy.run("狗的奔跑速度很快,通常能够达到60km/h")
运行后输出内容为:
狗的奔跑速度很快,通常能够达到60km/h
需要注意:
- 构造方法
__init__()
的主体,即便没有任何内容也不能空白,需要用pass
语句(第3行)。 - 即便
__init__()
没有有效参数,在创建实例时,方法后面的括号()
也不能省略(第7行)。
创建数据成员并访问
数据成员也称属性,指在类中定义的变量,根据定义位置,又可以分为:
- 类属性
- 实例属性
类属性
- 类属性是指,定义在类中,并且在方法体
__init__()
之外的属性 - 类属性可以在所有实例之间共享值
- 可以通过类名访问类的实例,还可以动态的为类和对象增加属性
- 动态为类的对象增加的属性,在各个对象之间是相互独立的。
class Dog:
nose = '鼻子很灵敏' # 类属性(鼻子)
tail = '尾巴略微上翘' # 类属性(尾巴)
number = 0 #记录数量
def __init__(self): # 定义构造方法
Dog.number += 1 #将数量 +1
print('\n我是第%d只狗,我属于狗类,我有以下特点:'%Dog.number) # 方法主体,引导语
print(Dog.nose) # 方法主体,鼻子
print(Dog.tail) # 方法主体,尾巴
list = [] # 定义一个空列表
for i in range(3): # 循环3次
list.append(Dog()) # 创建实例
print('\n一共有%d只狗'%Dog.number) #输出狗的只数
Dog.eye = '眼睛在夜里会发出幽幽的绿光' #通过类名,给类添加一个类属性
print('\n')
print('第1只狗的eye属性:',list[0].eye) #通过类的对象,输出第1只狗的 eye 属性
print('第2只狗的eye属性:',list[1].eye) #通过类的对象,输出第2只狗的 eye 属性
list[0].eye = '第1只狗的眼睛炯炯有神' #通过类的对象,给某一具体对象添加一个属性
print('\n通过类的对象更改后的eye属性:',list[0].eye) #通过类的对象,输出某一具体对象的属性
运行后,输出结果如下:
我是第1只狗,我属于狗类,我有以下特点:
鼻子很灵敏
尾巴略微上翘
我是第2只狗,我属于狗类,我有以下特点:
鼻子很灵敏
尾巴略微上翘
我是第3只狗,我属于狗类,我有以下特点:
鼻子很灵敏
尾巴略微上翘
一共有3只狗
第1只狗的eye属性: 眼睛在夜里会发出幽幽的绿光
第2只狗的eye属性: 眼睛在夜里会发出幽幽的绿光
通过类的对象更改后的eye属性: 第1只狗的眼睛炯炯有神
实例属性
- 定义在类的方法体
__init__()
中,通过self
关键词进行创建 - 只作用于当前实例对象,修改某一个对象的属性不影响其它对象的属性
class Dog:
def __init__(self): # 定义构造方法
self.nose = '鼻子很灵敏' # 实例属性(鼻子)
self.tail = '尾巴略微上翘' # 实例属性(尾巴)
print('\n狗类通常由以下特点:')
print(self.nose) # 访问实例属性
print(self.tail)
puppy = Dog() # 实例化类的对象
print(puppy.nose) # 通过对象访问类的属性
puppy_1 = Dog() # 实例化 第2个 类的对象
puppy_1.tail = '我的尾巴是黑色的。' # 修改第2个对象的属性
print('\npuppy:', puppy.tail)
print('\npuppy_1:',puppy_1.tail) # 对象putty_1的属性有变动,putty的属性不变
运行后输出结果如下:
狗类通常由以下特点:
鼻子很灵敏
尾巴略微上翘
鼻子很灵敏
狗类通常由以下特点:
鼻子很灵敏
尾巴略微上翘
puppy: 尾巴略微上翘
puppy_1: 我的尾巴是黑色的。
访问限制
在Jave中可以通过权限修饰符来指定访问权限,但在Python中没有权限修饰符。
在Python中,为了保证某些类内部的属性和方法不能被外部访问,可以通过在属性、方法名前添加下划线的形式,控制访问权限。
主要有三种形象形式:
_foo
,表示保护类型(protected)的成员,允许 类本身和子类可以访问__foo
,表示私有类型(private)的成员,只允许 类本身可以访问__foo__
,系统方法(如:__init__()
)
保护类型( protected
) _foo
- 允许类本身和子类可以访问(读/写)
- 可以通过类的实例(对象)进行访问(读/写)
- 不同实例(对象)之间的属性相互独立
class Dog:
_nose_dog = '狗的鼻子很灵敏' # 定义(写入)受保护类型的属性
def __init__(self):
print('\n通过内部构造方法__init__()访问:',Dog._nose_dog) # 访问(读取)保护类型的属性
dog = Dog() # 创建类的实例(对象)
print('通过对象直接访问:',dog._nose_dog) # 通过实例名,访问(读取)受保护类型的属性
dog._nose_dog = '我的鼻子是圆的' # 通过实例明,访问(写入,更改)受保护类型的属性
print('通过对象更改后的属性:',dog._nose_dog)
dog_1 = Dog()
print(dog_1._nose_dog)
dog_1._nose_dog = '我的鼻子是黑色的'
print(dog_1._nose_dog)
运行后,输出结果如下:
通过内部构造方法__init__()访问: 狗的鼻子很灵敏
通过对象直接访问: 狗的鼻子很灵敏
通过对象更改后的属性: 我的鼻子是圆的
通过内部构造方法__init__()访问: 狗的鼻子很灵敏
狗的鼻子很灵敏
我的鼻子是黑色的
私有类型( private
) __foo
- 只允许类本身可以访问
- 不可以通过类的实例进行访问
- 通过实例对象有其它方法可以访问(读/写)
类的实例名._类名__foo
- 不同实例之间的属性是相互独立的。
class Dog:
__nose_dog = '狗的鼻子很灵敏' # 定义(写入)私有类型的属性
def __init__(self):
print('\n通过内部构造方法__init__()访问:',Dog.__nose_dog) # 访问私有类型的属性
dog = Dog() # 创建类的实例(对象)
# print('通过对象直接访问:',dog.__nose_dog) # 通过实例名,访问(读取)私有类型的属性
# 以上语句错误,私有类型的属性不支持通过对象直接访问。
print('通过对象访问私有类型:',dog._Dog__nose_dog) # 访问(读取)私有类型的属性
dog._Dog__nose_dog = '我的鼻子是圆的'
print('通过对象更改后的私有类型的属性:',dog._Dog__nose_dog) # 访问(读取)私有类型的属性
dog_1 = Dog()
print(dog_1._Dog__nose_dog)
dog_1._Dog__nose_dog = '我的鼻子是黑色的'
print(dog_1._Dog__nose_dog)
运行后,输出结果如下:
通过内部构造方法__init__()访问: 狗的鼻子很灵敏
通过对象访问私有类型: 狗的鼻子很灵敏
通过对象更改后的私有类型的属性: 我的鼻子是圆的
通过内部构造方法__init__()访问: 狗的鼻子很灵敏
狗的鼻子很灵敏
我的鼻子是黑色的