面向对象-类与对象
Posted xuxuchao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象-类与对象相关的知识,希望对你有一定的参考价值。
三 类与对象
类即类别、种类,是面向对象设计最重要的概念,对象是特征与技能的结合体,而类则是一系列对象相似的特征与技能的结合体
那么问题来了,先有的一个个具体存在的对象(比如一个具体存在的人),还是先有的人类这个概念,这个问题需要分两种情况去看
在现实世界中:先有对象,再有类
世界上肯定是先出现各种各样的实际存在的物体,然后随着人类文明的发展,人类站在不同的角度总结出了不同的种类,如人类、动物类、植物类等概念
也就说,对象是具体的存在,而类仅仅只是一个概念,并不真实存在
在程序中:务必保证先定义类,后产生对象
这与函数的使用是类似的,先定义函数,后调用函数,类也是一样的,在程序中需要先定义类,后调用类
不一样的是,调用函数会执行函数体代码返回的是函数体执行的结果,而调用类会产生对象,返回的是对象
按照上述步骤,我们来定义一个类(我们站在老男孩学校的角度去看,在座的各位都是学生)
#在现实世界中,站在老男孩学校的角度:先有对象,再有类
对象1:李坦克
特征:
学校=oldboy
姓名=李坦克
性别=男
年龄=18
技能:
学习
吃饭
睡觉
对象2:王大炮
特征:
学校=oldboy
姓名=王大炮
性别=女
年龄=38
技能:
学习
吃饭
睡觉
对象3:牛榴弹
特征:
学校=oldboy
姓名=牛榴弹
性别=男
年龄=78
技能:
学习
吃饭
睡觉
现实中的老男孩学生类
相似的特征:
学校=oldboy
相似的技能:
学习
吃饭
睡觉
在现实世界中:先有对象,再有类
#在现实世界中,站在老男孩学校的角度:先有对象,再有类 对象1:李坦克 特征: 学校=oldboy 姓名=李坦克 性别=男 年龄=18 技能: 学习 吃饭 睡觉 对象2:王大炮 特征: 学校=oldboy 姓名=王大炮 性别=女 年龄=38 技能: 学习 吃饭 睡觉 对象3:牛榴弹 特征: 学校=oldboy 姓名=牛榴弹 性别=男 年龄=78 技能: 学习 吃饭 睡觉 现实中的老男孩学生类 相似的特征: 学校=oldboy 相似的技能: 学习 吃饭 睡觉
#在程序中,务必保证:先定义(类),后使用(产生对象)
PS:
1. 在程序中特征用变量标识,技能用函数标识
2. 因而类中最常见的无非是:变量和函数的定义
#程序中的类
class OldboyStudent:
school=‘oldboy‘
def learn(self):
print(‘is learning‘)
def eat(self):
print(‘is eating‘)
def sleep(self):
print(‘is sleeping‘)
#注意:
1.类中可以有任意python代码,这些代码在类定义阶段便会执行
2.因而会产生新的名称空间,用来存放类的变量名与函数名,可以通过OldboyStudent.__dict__查看
3.对于经典类来说我们可以通过该字典操作类名称空间的名字(新式类有限制),但python为我们提供专门的.语法
4.点是访问属性的语法,类中定义的名字,都是类的属性
#程序中类的用法
.:专门用来访问属性,本质操作的就是__dict__
OldboyStudent.school #等于经典类的操作OldboyStudent.__dict__[‘school‘]
OldboyStudent.school=‘Oldboy‘ #等于经典类的操作OldboyStudent.__dict__[‘school‘]=‘Oldboy‘
OldboyStudent.x=1 #等于经典类的操作OldboyStudent.__dict__[‘x‘]=1
del OldboyStudent.x #等于经典类的操作OldboyStudent.__dict__.pop(‘x‘)
#程序中的对象
#调用类,或称为实例化,得到对象
s1=OldboyStudent()
s2=OldboyStudent()
s3=OldboyStudent()
#如此,s1、s2、s3都一样了,而这三者除了相似的属性之外还各种不同的属性,这就用到了__init__
#注意:该方法是在对象产生之后才会执行,只用来为对象进行初始化操作,可以有任意代码,但一定不能有返回值
class OldboyStudent:
......
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
......
s1=OldboyStudent(‘李坦克‘,‘男‘,18) #先调用类产生空对象s1,然后调用OldboyStudent.__init__(s1,‘李坦克‘,‘男‘,18)
s2=OldboyStudent(‘王大炮‘,‘女‘,38)
s3=OldboyStudent(‘牛榴弹‘,‘男‘,78)
#程序中对象的用法
#执行__init__,s1.name=‘牛榴弹‘,很明显也会产生对象的名称空间
s2.__dict__
{‘name‘: ‘王大炮‘, ‘age‘: ‘女‘, ‘sex‘: 38}
s2.name #s2.__dict__[‘name‘]
s2.name=‘王三炮‘ #s2.__dict__[‘name‘]=‘王三炮‘
s2.course=‘python‘ #s2.__dict__[‘course‘]=‘python‘
del s2.course #s2.__dict__.pop(‘course‘)
在程序中:先定义类,后产生对象
#在程序中,务必保证:先定义(类),后使用(产生对象) PS: 1. 在程序中特征用变量标识,技能用函数标识 2. 因而类中最常见的无非是:变量和函数的定义 #程序中的类 class OldboyStudent: school=‘oldboy‘ def learn(self): print(‘is learning‘) def eat(self): print(‘is eating‘) def sleep(self): print(‘is sleeping‘) #注意: 1.类中可以有任意python代码,这些代码在类定义阶段便会执行 2.因而会产生新的名称空间,用来存放类的变量名与函数名,可以通过OldboyStudent.__dict__查看 3.对于经典类来说我们可以通过该字典操作类名称空间的名字(新式类有限制),但python为我们提供专门的.语法 4.点是访问属性的语法,类中定义的名字,都是类的属性 #程序中类的用法 .:专门用来访问属性,本质操作的就是__dict__ OldboyStudent.school #等于经典类的操作OldboyStudent.__dict__[‘school‘] OldboyStudent.school=‘Oldboy‘ #等于经典类的操作OldboyStudent.__dict__[‘school‘]=‘Oldboy‘ OldboyStudent.x=1 #等于经典类的操作OldboyStudent.__dict__[‘x‘]=1 del OldboyStudent.x #等于经典类的操作OldboyStudent.__dict__.pop(‘x‘) #程序中的对象 #调用类,或称为实例化,得到对象 s1=OldboyStudent() s2=OldboyStudent() s3=OldboyStudent() #如此,s1、s2、s3都一样了,而这三者除了相似的属性之外还各种不同的属性,这就用到了__init__ #注意:该方法是在对象产生之后才会执行,只用来为对象进行初始化操作,可以有任意代码,但一定不能有返回值 class OldboyStudent: ...... def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex ...... s1=OldboyStudent(‘李坦克‘,‘男‘,18) #先调用类产生空对象s1,然后调用OldboyStudent.__init__(s1,‘李坦克‘,‘男‘,18) s2=OldboyStudent(‘王大炮‘,‘女‘,38) s3=OldboyStudent(‘牛榴弹‘,‘男‘,78) #程序中对象的用法 #执行__init__,s1.name=‘牛榴弹‘,很明显也会产生对象的名称空间 s2.__dict__ {‘name‘: ‘王大炮‘, ‘age‘: ‘女‘, ‘sex‘: 38} s2.name #s2.__dict__[‘name‘] s2.name=‘王三炮‘ #s2.__dict__[‘name‘]=‘王三炮‘ s2.course=‘python‘ #s2.__dict__[‘course‘]=‘python‘ del s2.course #s2.__dict__.pop(‘course‘)
!!!细说__init__方法!!!
#方式一、为对象初始化自己独有的特征
class People:
country=‘China‘
x=1
def run(self):
print(‘----->‘, self)
# 实例化出三个空对象
obj1=People()
obj2=People()
obj3=People()
# 为对象定制自己独有的特征
obj1.name=‘egon‘
obj1.age=18
obj1.sex=‘male‘
obj2.name=‘lxx‘
obj2.age=38
obj2.sex=‘female‘
obj3.name=‘alex‘
obj3.age=38
obj3.sex=‘female‘
# print(obj1.__dict__)
# print(obj2.__dict__)
# print(obj3.__dict__)
# print(People.__dict__)
#方式二、为对象初始化自己独有的特征
class People:
country=‘China‘
x=1
def run(self):
print(‘----->‘, self)
# 实例化出三个空对象
obj1=People()
obj2=People()
obj3=People()
# 为对象定制自己独有的特征
def chu_shi_hua(obj, x, y, z): #obj=obj1,x=‘egon‘,y=18,z=‘male‘
obj.name = x
obj.age = y
obj.sex = z
chu_shi_hua(obj1,‘egon‘,18,‘male‘)
chu_shi_hua(obj2,‘lxx‘,38,‘female‘)
chu_shi_hua(obj3,‘alex‘,38,‘female‘)
#方式三、为对象初始化自己独有的特征
class People:
country=‘China‘
x=1
def chu_shi_hua(obj, x, y, z): #obj=obj1,x=‘egon‘,y=18,z=‘male‘
obj.name = x
obj.age = y
obj.sex = z
def run(self):
print(‘----->‘, self)
obj1=People()
# print(People.chu_shi_hua)
People.chu_shi_hua(obj1,‘egon‘,18,‘male‘)
obj2=People()
People.chu_shi_hua(obj2,‘lxx‘,38,‘female‘)
obj3=People()
People.chu_shi_hua(obj3,‘alex‘,38,‘female‘)
# 方式四、为对象初始化自己独有的特征
class People:
country=‘China‘
x=1
def __init__(obj, x, y, z): #obj=obj1,x=‘egon‘,y=18,z=‘male‘
obj.name = x
obj.age = y
obj.sex = z
def run(self):
print(‘----->‘, self)
obj1=People(‘egon‘,18,‘male‘) #People.__init__(obj1,‘egon‘,18,‘male‘)
obj2=People(‘lxx‘,38,‘female‘) #People.__init__(obj2,‘lxx‘,38,‘female‘)
obj3=People(‘alex‘,38,‘female‘) #People.__init__(obj3,‘alex‘,38,‘female‘)
# __init__方法
# 强调:
# 1、该方法内可以有任意的python代码
# 2、一定不能有返回值
class People:
country=‘China‘
x=1
def __init__(obj, name, age, sex): #obj=obj1,x=‘egon‘,y=18,z=‘male‘
# if type(name) is not str:
# raise TypeError(‘名字必须是字符串类型‘)
obj.name = name
obj.age = age
obj.sex = sex
def run(self):
print(‘----->‘, self)
# obj1=People(‘egon‘,18,‘male‘)
obj1=People(3537,18,‘male‘)
# print(obj1.run)
# obj1.run() #People.run(obj1)
# print(People.run)
!!!__init__方法之为对象定制自己独有的特征
#方式一、为对象初始化自己独有的特征 class People: country=‘China‘ x=1 def run(self): print(‘----->‘, self) # 实例化出三个空对象 obj1=People() obj2=People() obj3=People() # 为对象定制自己独有的特征 obj1.name=‘egon‘ obj1.age=18 obj1.sex=‘male‘ obj2.name=‘lxx‘ obj2.age=38 obj2.sex=‘female‘ obj3.name=‘alex‘ obj3.age=38 obj3.sex=‘female‘ # print(obj1.__dict__) # print(obj2.__dict__) # print(obj3.__dict__) # print(People.__dict__) #方式二、为对象初始化自己独有的特征 class People: country=‘China‘ x=1 def run(self): print(‘----->‘, self) # 实例化出三个空对象 obj1=People() obj2=People() obj3=People() # 为对象定制自己独有的特征 def chu_shi_hua(obj, x, y, z): #obj=obj1,x=‘egon‘,y=18,z=‘male‘ obj.name = x obj.age = y obj.sex = z chu_shi_hua(obj1,‘egon‘,18,‘male‘) chu_shi_hua(obj2,‘lxx‘,38,‘female‘) chu_shi_hua(obj3,‘alex‘,38,‘female‘) #方式三、为对象初始化自己独有的特征 class People: country=‘China‘ x=1 def chu_shi_hua(obj, x, y, z): #obj=obj1,x=‘egon‘,y=18,z=‘male‘ obj.name = x obj.age = y obj.sex = z def run(self): print(‘----->‘, self) obj1=People() # print(People.chu_shi_hua) People.chu_shi_hua(obj1,‘egon‘,18,‘male‘) obj2=People() People.chu_shi_hua(obj2,‘lxx‘,38,‘female‘) obj3=People() People.chu_shi_hua(obj3,‘alex‘,38,‘female‘) # 方式四、为对象初始化自己独有的特征 class People: country=‘China‘ x=1 def __init__(obj, x, y, z): #obj=obj1,x=‘egon‘,y=18,z=‘male‘ obj.name = x obj.age = y obj.sex = z def run(self): print(‘----->‘, self) obj1=People(‘egon‘,18,‘male‘) #People.__init__(obj1,‘egon‘,18,‘male‘) obj2=People(‘lxx‘,38,‘female‘) #People.__init__(obj2,‘lxx‘,38,‘female‘) obj3=People(‘alex‘,38,‘female‘) #People.__init__(obj3,‘alex‘,38,‘female‘) # __init__方法 # 强调: # 1、该方法内可以有任意的python代码 # 2、一定不能有返回值 class People: country=‘China‘ x=1 def __init__(obj, name, age, sex): #obj=obj1,x=‘egon‘,y=18,z=‘male‘ # if type(name) is not str: # raise TypeError(‘名字必须是字符串类型‘) obj.name = name obj.age = age obj.sex = sex def run(self): print(‘----->‘, self) # obj1=People(‘egon‘,18,‘male‘) obj1=People(3537,18,‘male‘) # print(obj1.run) # obj1.run() #People.run(obj1) # print(People.run)
PS:
1. 站的角度不同,定义出的类是截然不同的,详见面向对象实战之需求分析
2. 现实中的类并不完全等于程序中的类,比如现实中的公司类,在程序中有时需要拆分成部门类,业务类......
3. 有时为了编程需求,程序中也可能会定义现实中不存在的类,比如策略类,现实中并不存在,但是在程序中却是一个很常见的类
#python为类内置的特殊属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)
类的特殊属性(了解即可)
#python为类内置的特殊属性 类名.__name__# 类的名字(字符串) 类名.__doc__# 类的文档字符串 类名.__base__# 类的第一个父类(在讲继承时会讲) 类名.__bases__# 类所有父类构成的元组(在讲继承时会讲) 类名.__dict__# 类的字典属性 类名.__module__# 类定义所在的模块 类名.__class__# 实例对应的类(仅新式类中)
!!!补充说明:从代码级别看面向对象 !!!
#1、在没有学习类这个概念时,数据与功能是分离的
def exc1(host,port,db,charset):
conn=connect(host,port,db,charset)
conn.execute(sql)
return xxx
def exc2(host,port,db,charset,proc_name)
conn=connect(host,port,db,charset)
conn.call_proc(sql)
return xxx
#每次调用都需要重复传入一堆参数
exc1(‘127.0.0.1‘,3306,‘db1‘,‘utf8‘,‘select * from tb1;‘)
exc2(‘127.0.0.1‘,3306,‘db1‘,‘utf8‘,‘存储过程的名字‘)
#2、我们能想到的解决方法是,把这些变量都定义成全局变量
HOST=‘127.0.0.1’
PORT=3306
DB=‘db1’
CHARSET=‘utf8’
def exc1(host,port,db,charset):
conn=connect(host,port,db,charset)
conn.execute(sql)
return xxx
def exc2(host,port,db,charset,proc_name)
conn=connect(host,port,db,charset)
conn.call_proc(sql)
return xxx
exc1(HOST,PORT,DB,CHARSET,‘select * from tb1;‘)
exc2(HOST,PORT,DB,CHARSET,‘存储过程的名字‘)
#3、但是2的解决方法也是有问题的,按照2的思路,我们将会定义一大堆全局变量,这些全局变量并没有做任何区分,即能够被所有功能使用,然而事实上只有HOST,PORT,DB,CHARSET是给exc1和exc2这两个功能用的。言外之意:我们必须找出一种能够将数据与操作数据的方法组合到一起的解决方法,这就是我们说的类了
class mysqlHandler:
def __init__(self,host,port,db,charset=‘utf8‘):
self.host=host
self.port=port
self.db=db
self.charset=charset
def exc1(self,sql):
conn=connect(self.host,self.port,self.db,self.charset)
res=conn.execute(sql)
return res
def exc2(self,sql):
conn=connect(self.host,self.port,self.db,self.charset)
res=conn.call_proc(sql)
return res
obj=MySQLHandler(‘127.0.0.1‘,3306,‘db1‘)
obj.exc1(‘select * from tb1;‘)
obj.exc2(‘存储过程的名字‘)
#改进
class MySQLHandler:
def __init__(self,host,port,db,charset=‘utf8‘):
self.host=host
self.port=port
self.db=db
self.charset=charset
self.conn=connect(self.host,self.port,self.db,self.charset)
def exc1(self,sql):
return self.conn.execute(sql)
def exc2(self,sql):
return self.conn.call_proc(sql)
obj=MySQLHandler(‘127.0.0.1‘,3306,‘db1‘)
obj.exc1(‘select * from tb1;‘)
obj.exc2(‘存储过程的名字‘)
数据与专门操作该数据的功能组合到一起
#1、在没有学习类这个概念时,数据与功能是分离的 def exc1(host,port,db,charset): conn=connect(host,port,db,charset) conn.execute(sql) return xxx def exc2(host,port,db,charset,proc_name) conn=connect(host,port,db,charset) conn.call_proc(sql) return xxx #每次调用都需要重复传入一堆参数 exc1(‘127.0.0.1‘,3306,‘db1‘,‘utf8‘,‘select * from tb1;‘) exc2(‘127.0.0.1‘,3306,‘db1‘,‘utf8‘,‘存储过程的名字‘) #2、我们能想到的解决方法是,把这些变量都定义成全局变量 HOST=‘127.0.0.1’ PORT=3306 DB=‘db1’ CHARSET=‘utf8’ def exc1(host,port,db,charset): conn=connect(host,port,db,charset) conn.execute(sql) return xxx def exc2(host,port,db,charset,proc_name) conn=connect(host,port,db,charset) conn.call_proc(sql) return xxx exc1(HOST,PORT,DB,CHARSET,‘select * from tb1;‘) exc2(HOST,PORT,DB,CHARSET,‘存储过程的名字‘) #3、但是2的解决方法也是有问题的,按照2的思路,我们将会定义一大堆全局变量,这些全局变量并没有做任何区分,即能够被所有功能使用,然而事实上只有HOST,PORT,DB,CHARSET是给exc1和exc2这两个功能用的。言外之意:我们必须找出一种能够将数据与操作数据的方法组合到一起的解决方法,这就是我们说的类了 class MySQLHandler: def __init__(self,host,port,db,charset=‘utf8‘): self.host=host self.port=port self.db=db self.charset=charset def exc1(self,sql): conn=connect(self.host,self.port,self.db,self.charset) res=conn.execute(sql) return res def exc2(self,sql): conn=connect(self.host,self.port,self.db,self.charset) res=conn.call_proc(sql) return res obj=MySQLHandler(‘127.0.0.1‘,3306,‘db1‘) obj.exc1(‘select * from tb1;‘) obj.exc2(‘存储过程的名字‘) #改进 class MySQLHandler: def __init__(self,host,port,db,charset=‘utf8‘): self.host=host self.port=port self.db=db self.charset=charset self.conn=connect(self.host,self.port,self.db,self.charset) def exc1(self,sql): return self.conn.execute(sql) def exc2(self,sql): return self.conn.call_proc(sql) obj=MySQLHandler(‘127.0.0.1‘,3306,‘db1‘) obj.exc1(‘select * from tb1;‘) obj.exc2(‘存储过程的名字‘)
以上是关于面向对象-类与对象的主要内容,如果未能解决你的问题,请参考以下文章