一、面向对象编程的初步认识(然你大体上了解什么是面向对象)
1、什么是面向对象编程
a、 举个通俗的例子:现在有个哥们(wc)要洗身上的衣服,那么他要做两件事,1、脱衣服 2、洗衣服,那么面向过程就像是一套完整的流程,wc把衣服脱掉、洗衣服执行了这么一个过程然后结束,面向对象呢首先是先将wc这个哥们抽象出来,裸体相见,然后给这个哥们一个名字,一个年龄,一个上衣,一条裤子,一个脱衣服的能力,一个洗衣服的能力,然后通过你已经赋予他的能力来做他能做的事情,这就是面向对象中创建对象(一个有名字穿着衣服的人),使用对象的方法(洗衣服等的能力)的过程。听完这个大家觉得可能还是一脸懵逼,那么下面我们来看一段面向对象的代码。
b 、首先来看一段代码:
importtimeclassSmting: #通过关键字class进行类的定义,就想函数的def一样,起到声明的作用,形式就是 "class 类名:"def __init__(self, sm_name, sm_age, sm_shirt, sm_pants):
# __init__方法是构造方法,根据类创建对象的时候自动执行 (这个后面讲)
#self 为实例化的对象本身,即被类实例化出来的对象
self.name=sm_name
self.age=sm_age
self.shirt= sm_shirt #1:表示在身上 0:表示不在身上 2:表示洗干净了
self.pants = sm_pants #1:表示在身上 0:表示不在身上 2:表示洗干净了
deftake_off_clothes(self):#print('%s正在脱衣服。。。'%self.name)
print(self.name + '正在脱衣服。。。')
self.shirt=0
time.sleep(1)print(self.name + '已经脱掉了外套。。。')
self.pants=0
time.sleep(1)print(self.name + '已经脱掉了裤子。。。')print(self.name + '脱衣服完毕!!!')defwash_clothes(self):print(self.name + '正在洗衣服。。。洗衣机压力有点大。。。')
time.sleep(2)
self.shirt= 2self.pants= 2
print(self.name + '大喊:穿了4个月的内裤终于洗出来了! WOW!')returnself.shirt
wc= Smting('wc',60,1,1) #实例化类,创建对象,并起一个名字(即给对象命名,变量名指向self,就像a = 1,而这个变量a指向的是这个数字1的内存地址一样),这时候会自动执行类中的__init__方法 (还可以带参数,后面讲)
#print(wc.name)print(wc.age)
wc.name= 'SBwc'
print(wc.name)
wc.take_off_clothes()
wc.wash_clothes()
面向过程:
def do_sm_laundry(sm_name, sm_age, sm_shirt, sm_pants): #洗洗衣服
print(sm_name + '正在脱衣服。。。')
sm_shirt=0
time.sleep(1)print(sm_name + '已经脱掉了外套。。。')
sm_pants=0
time.sleep(1)print(sm_name + '已经脱掉了裤子。。。')print(sm_name + '脱衣服完毕!!!')print(sm_name + '正在洗衣服。。。洗衣机压力有点大。。。')
time.sleep(2)
sm_shirt= 2sm_pants= 2
print(sm_name + '大喊:穿了4个月的内裤终于洗出来了! WOW!')returnsm_shirt,sm_pants
do_sm_laundry('wc',60,1,1)
那么有人说了我怎么看着面向过程简单的,代码少啊,那么需求来了:
#我衣服早就脱完了,我现在就想洗衣服,咋整
#如果现在再用面向过程的变成是不是需要将整个函数执行一下,但是你发现,他的衣服已经脱了啊,怎么办,只能是改函数,或者是copy有一份,然后删除其中脱衣服的部分,对吧
#但是如果是面向对象编程,那么你只需要创建一个对象,然后使用这个对象中洗衣服的功能就可以了,那么我们来看
naked_wc = Smting('wc',60,0,0)
shirt_val=naked_wc.wash_clothes()print(shirt_val)
但是这时候又有同学说了,这个同学不知道怎么这么多话
# 我写几个小功能函数,不是也能搞定吗,想用哪个功能就调用哪个函数,
# 对,这样说是没有问题,所以面向对象和面向过程的编程没有本质上的优劣之分,但是实际的开发中,多数的功能是比较复杂的,将复杂的功能抽象出来,有助于你对功能的理解和对功能的拓展,另外也省去了各个功能之间的参数传递的麻烦,见下面的函数
deftake_off_cloth(sm_name, sm_age, sm_shirt, sm_pants):print(sm_name + '正在脱衣服。。。')
sm_shirt=0
time.sleep(1)print(sm_name + '已经脱掉了外套。。。')
sm_pants=0
time.sleep(1)print(sm_name + '已经脱掉了裤子。。。')print(sm_name + '脱衣服完毕!!!')returnsm_name, sm_age, sm_shirt, sm_pantsdefwash_cloth(sm_name, sm_age, sm_shirt, sm_pants):print(sm_name + '正在洗衣服。。。洗衣机压力有点大。。。')
time.sleep(2)
sm_shirt= 2sm_pants= 2
print(sm_name + '大喊:穿了4个月的内裤终于洗出来了! WOW!')returnsm_shirt,sm_pants
name,age,shirt,pants= take_off_cloth('wc',60,0,0) #一个告诉另外一个功能你所处的状态,一直做这样的参数传递,是不是很麻烦,而面向对象中的对象是不是就将自己的状态记录好了,在接着使用自己的功能就可以了
wash_cloth(name,age,shirt,pants)
二、面向对象深入学习
1、看一下类的形式 (拿上面的代码来看)
2、来看一下中里面的self是个什么东西
self 代表的是类的实例,而非类,通俗的看self就是一个裸体的对象(人物),那么类呢就是给这个人物加上的各种属性(性别、年龄),技能(能洗衣服、能脱衣服)等然后封在一起的一个大包裹
然后大家看下面一个例子
classTest:defshow(self):print(self)print(self.__class__)
tt=Test()
print(tt)
tt.show()
执行结果如下
<__main__.Test object at 0x000000000284E080>
<__main__.Test object at 0x000000000284E080>
从上面的例子中可以很明显的看出,self代表的是类的实例。而self.class则指向类。
self不必非写成self
有同学问了,那self这个东东,就是必须叫self吗,no no no,你想想,这就相当于一个新生的人,并赋予一个标志路人甲一样是大家约定俗成的,我就不让他叫路人甲,我就叫做this行不行,why not!
看代码:
classTest:defshow(this):print(this)print(this.__class__)
t=Test()
t.show()
改成this后,运行结果完全一样。
当然,最好还是尊重约定俗成的习惯,使用self。
self可以不写吗
在Python的解释器内部,当我们调用t.prt()时,实际上Python解释成Test.show(t),也就是说把self替换成类的实例。
有兴趣的同学可以把上面的t.show()一行改写一下,运行后的实际结果完全相同。
其实定义在类中的可调用对象, 一般被称作方法(method) 是一种特殊的函数. 它们与正常函数的不同之处在于, 当你用n个参数调用它时, 实际上会隐式地传递给它第n+1个参数.
这在C++和Java等语言里同样可以体现, method中可以使用一个特殊的this变量.
举个例子:
a = A() # a 是A类的一个实例对象
a.method(c,d) 实质上就是调用class.method(a, c, d)
而在python中, 要求method定义时就显示声明存在一个self参数, 它就是调用上例中传递的a.
实际上已经部分说明了self在定义时不可以省略,如果非要试一下,那么请看下面
classTest:defprt():print(self)
t=Test()
t.show()
运行时提醒错误如下:show在定义时没有参数,但是我们运行时强行传了一个参数。
由于上面解释过了t.show()等同于Test.show(t),所以程序提醒我们多传了一个参数t。
Traceback (most recent call last):
File"h.py", line 6, in t.prt()
TypeError: prt() takes 0 positional arguments but1 was given
3、外部动态给对象添加属性
classBar:deffoo(self,arg):print(self,self.name,arg)
z=Bar()
z.name= 'sb' #大家说这样行不行,当然行啦,刚才不是说了吗,z就相当于指向的self,这样写就相当于给self添加了一个属性name(并且是个临时属性,当我们创建其他的实例的时候,其他实例是没有这个属性的
,要注意这里),对吧,不过一般不这么写,特殊情况下需要你动态添加的时候采用,并且一定要注意程序的顺序。z.foo(666) #如果限制性z.foo(666),那么就会报错
好,那么在说一下构造方法,那么本节课就结束了,构造方法__init__(一般是做初始化用的,在执行之前有些东西是需要创建好的,就写到init方法中,就是前面我们说的人物的属性,装备等,但是人物能做的事情是写在其他方法里面去的)
ok,那么课后同学们写别着急问问题,要先整理、在整理的过程中不断的思考,让自己理解,然后发现实在理解不了的问题,在找老师,因为你自己能够通过自己来消化吸收,对你是十分有好处的,无论是在学习能力和理解能力上都会有所提升
。并且,希望咱们将时间管理起来,老师的时间也是有限的,你自己的时间也是有限的,如果说自己还没有动脑筋思考,上来就问,你肯定学的很慢。ok吗,好,那这节课就结束了,下节课我们将面向对象的三大特征以及一些其他的参数形式和方法形式,谢谢大家