【十三】python面向对象之类和对象

2019-06-13 10:58:21 浏览数 (1)


一、什么是类和对象

,可以看成种类,类型,从一组对象中提取到的相似部分。所有的对象都属于一个类,称为类的实例。数据类型就是类。

对象(object)基本上可以看做数据(特性)以及由一系列可以存取、操作这些数据的方法所组成的集合。

1 2

print(int) print(Garen)

输出结果:

1 2

<class 'int'> <class '__main__.Garen'>

二、类 

1、初始类

1 声明类 (和声明函数很相似)

1 2 3 4

类的定义格式 class 类名: '类的文档字符串' 类体

2、创建一个类

1 2

class Data: pass

*Python编程中习惯类名使用单数单词并且首字母大写

类是数据与函数的结合,二者称为类的属性

1 2 3 4

class Garen: #定义英雄盖伦的类,不同的玩家可以用它实例出自己英雄; camp='Demacia' #所有玩家的英雄(盖伦)的阵营都是Demacia; def attack(self,enemy): #普通攻击技能,enemy是敌人; enemy.life_value-=self.aggressivity #根据自己的攻击力,攻击敌人就减掉敌人的生命值。

3、类的作用

3.1、属性引用(类名.属性)

(1)引用类的数据属性(类名.变量名)

1

print(Garen.camp) # 引用类的数据属性,该属性与所有对象/实例共享

输出结果为:

1

Demacia

 (2)引用类的函数属性(类名.函数名)

1

print(Garen.attack) #引用类的函数属性,该属性也共享

输出结果为:

1

<function Garen.attack at 0x00000059CE8FAF28>

(3)类的属性操作

1 2

Garen.name='Garen1' #增加属性 print(Garen.name) #查询属性

输出结果为:

1

Garen1

1 2 3

del Garen.name #删除属性 print(Garen.name)

输出结果为:

1

AttributeError: type object 'Garen' has no attribute 'name' #报错

1 2

Garen.camp="aaaa" #修改属性 print(Garen.camp)

输出结果为:

1

aaaa

3.2、查看类的属性

dir(类名):查出的是一个名字列表

类名.__dict__:查出的是一个字典,key为属性名,value为属性值

3.3、特殊的类属性

类名.__name__# 类的名字(字符串)

类名.__doc__# 类的文档字符串

类名.__base__# 类的第一个父类(在讲继承时会讲)

类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)

类名.__dict__# 类的字典属性

类名.__module__# 类定义所在的模块

类名.__class__# 实例对应的类(仅新式类中)

3.4、实例化

(1)__init__实例化

类名加括号就是实例化,会自动触发__init__函数的运行,可以用他来为每个实例定制自己的特性

1 2 3 4 5 6 7 8

class Garen: camp='Demacia' def __init__(self,nickname,aggressivity=58,life_value=455): self.nickname=nickname #为自己的盖伦起个别名; self.aggressivity=aggressivity #英雄都有自己的攻击力; self.life_value=life_value #英雄都有自己的生命值; def attack(self,enemy): print("attack %s" % enemy)

实例化:类名 括号

1

g1=Garen('草丛伦')

#就是在执行Garen.__int__(g1,’草丛伦’),然后执行__init__内的代码g1.nickname=’草丛伦’等  

(2)self作用

self的作用是在实例化时自动将对象/实例本身传给__init__的第一个参数,self可以是任意名字,但是self是大家公认的。

4、抽象类

如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。

从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。

从实现角度来看,抽象类与普通类的不同之处在于:抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似,但其实是不同的,即将揭晓答案

4.1、在python中实现实现抽象类

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

#一切皆文件 import abc #利用abc模块实现抽象类 class All_file(metaclass=abc.ABCMeta): all_type='file' @abc.abstractmethod #定义抽象方法,无需实现功能 def read(self): '子类必须定义读功能' pass @abc.abstractmethod #定义抽象方法,无需实现功能 def write(self): '子类必须定义写功能' pass # class Txt(All_file): # pass # # t1=Txt() #报错,子类没有定义抽象方法 class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法 def read(self): print('文本数据的读取方法') def write(self): print('文本数据的读取方法') class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法 def read(self): print('硬盘数据的读取方法') def write(self): print('硬盘数据的读取方法') class Process(All_file): #子类继承抽象类,但是必须定义read和write方法 def read(self): print('进程数据的读取方法') def write(self): print('进程数据的读取方法') wenbenwenjian=Txt() yingpanwenjian=Sata() jinchengwenjian=Process() #这样大家都是被归一化了,也就是一切皆文件的思想 wenbenwenjian.read() yingpanwenjian.write() jinchengwenjian.read() print(wenbenwenjian.all_type) print(yingpanwenjian.all_type) print(jinchengwenjian.all_type)

5、抽象类与接口  

抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计

6、类名称空间

创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性

而类的良好总属性:数据属性和函数属性

其中类的数据属性是共享给所有对象

1 2

print(id(g1.camp)) #引用的地址是一样的 print(id(Garen.camp))

输出结果为:

1 2

364617767096 364617767096

其中类的函数属性是绑定到所有对象

1 2

print(id(g1.attack)) #两个引用地址不一样 print(id(Garen.attack))

输出结果为:

1 2

1009949719304 1009951072464

分析:g1.attack就是在执行Garen.attack的功能,python的class机制会将Garen的函数属性attack绑定给g1,g 1相当于拿到了一个指针,指向Garen类的attack功能。除此之外,g1.attack()会将g1传给attack的第一个参数。

三、对象(实例)

对象是关于类而实际存在的一个例子,即实例

#类实例化得到g1这个实例

1 2 3 4 5 6 7 8 9 10

class Garen: camp='Demacia' def __init__(self,nickname,aggressivity=58,life_value=455): self.nickname=nickname #为自己的盖伦起个别名; self.aggressivity=aggressivity #英雄都有自己的攻击力; self.life_value=life_value #英雄都有自己的生命值; def attack(self,enemy): print("attack %s" % enemy) g1=Garen('草丛伦')

1、对象的属性引用和绑定方法

(1)对象(实例)只有一种作用:属性引用

格式: 实例名.类的变量名

实例名.绑定方法

实例名.实例自己的变量名

1 2 3

print(g1.nickname) print(g1.aggressivity) print(g1.life_value)

输出结果为:

1 2 3

草丛伦 58 455

(2)对象的属性操作

查看属性信息

1

print(g1.nickname)

输出结果:

1

草丛伦

修改属性信息

1 2

g1.nickname="伦哥" print(g1.nickname)

输出结果为:

1

添加属性

1 2

g1.sex="female" print(g1.sex)

输出结果为:

1

Female

删除属性:

1 2

del g1.sex print(g1.sex)

输出结果为:

1

AttributeError: 'Garen' object has no attribute 'sex' #报错

(3)查看实例属性

同样是dir和内置__dict__两种方式

特殊实例属性

__class__

__dict__

(4)对象(实例)的绑定方法

对象本身只有数据属性,但是python的class机制会将类的函数绑定到对象上,称为对象的方法,或者叫绑定方法。

1 2

print(g1.attack) #对象的绑定方法 print(Garen.attack) #对象的绑定方法attack本质就是调用类的函数attack的功能,二者是一种绑定关系

输出结果为:

1 2

<bound method Garen.attack of <__main__.Garen object at 0x00000017370815F8>> <function Garen.attack at 0x0000001737085048>

对象的绑定方法的特别之处在于:obj.func()会把obj传给func的第一个参数

2、对象的交互

仿照Garen类创建一个Riven类:

实例Riven类

交互:瑞雯攻击草丛伦

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

class Riven: camp='Noxus' def __init__(self,nickname,aggressivity=54,life_value=414): self.nickname=nickname #为自己的瑞雯起个别名; self.aggressivity=aggressivity #英雄都有自己的攻击力; self.life_value=life_value #英雄都有自己的生命值; def attack(self,enemy): print("attack %s" % enemy) enemy.life_value -= self.aggressivity g1=Garen('草丛伦') r1=Riven('瑞雯') print(g1.life_value) r1.attack(g1) print(g1.life_value)

输出结果为:

1 2 3

455 瑞雯 attack 草丛伦 401

3、 对象(实例)名称空间

创建一个对象(实例)就会创建一个对象(实例)的名称空间,存放对象(实例)的名字,称为对象(实例)的属性

在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类中找不到就找父类。最后找不到就抛出异常。

0 人点赞