Python进阶学习之——类和对象
致力于为每一位用户免费提供更优质技术帮助与资源供给,感谢支持!
在原来我发布过Python入门学习的学习笔记,到迟迟没有更新进阶学习的博客。今天下午没课就更新一下。上次发布的入门学习全部都是在一篇博客里的,看起来冗余且没有阅读兴趣,这回我就分开来写吧。以下全部为个人学习后的理解,如有错误,还请指正。
第一讲:
一、对象
下面我来给大家介绍对象。对象是模拟现实世界,将数据和代码封装起来。例如一个人,从外貌看他长得高,长的帅,两条腿,一个头。另一方面看他能做什么,他会写代码,会唱歌,会打游戏。我们把静态的描述称为属性(类比于外貌),动态的描述称为方法(类比于会写代码)。
下面给大家举个例子:
class Girl: #新建一个类
#属性
look = '可爱'
height = '165cm'
age = '20'
boyriend = '暂无'
#方法
def code(self):
print("我会打代码")
def say(self):
print("我喜欢夜寒哥哥")
def wechat(self):
print("关注微信公众号'夜寒信息'")
def sleep(self):
print("我去和夜寒哥哥睡觉了")
上面创建了一个类,注意类名以大写字母开头。类就相当于在生产中的一个模具,我们要利用它,就得实例化一个对象,然后才能调用它的内部的属性及方法。
以下给出方式:
>>> g = Girl() #实例化对象给变量g
>>> g.look #查看look属性
'可爱'
>>> g.height #查看height属性
'165cm'
>>> g.say() #调用say方法,注意加括号
我喜欢夜寒哥哥
>>> g.wechat() #调用wechat方法,注意加括号
关注微信公众号'夜寒信息'
>>> g.sleep() #调用sleep方法,注意加括号
我去和夜寒哥哥睡觉了
注意,class所创建的Girl是类,并不是对象。只有将类实例化给一个变量,那个变量才称之为对象,例如例子中的g
二、封装
封装就类似于打包,类中封装了属性和方法,打包成为一个模块供用户使用。同时类又有信息隐蔽功能,就像是你的游戏账号是一个类,里面有符文,点券。你把你的账号给你的女朋友玩,就类比于是把类分配给了对象。但你只想让她玩,不想让她熔你的符文,花你的点券。于是你将游戏账号设置了二级密码,将它封装起来。它可以使用你的符文,但不能销毁。
下面举个例子
>>> ls=[] #新建一个列表
>>> ls.append(1) #使用append()函数添加一个,在列表内1
>>> ls
[1] #1添加入ls中
我们知道在往列表内添加数据要使用append方法,但我们不知道列表的类中append 方法是怎么实现的,这就是封装
三、继承
继承就是子类共享父类的属性和方法,就像是传家宝,一代传一代,传同样的东西
下面举个例子
>>> class Boy(Girl): #新建一个Boy类,在括号内写要继承的父类名
pass
>>> b = Boy() #将类实例化
>>> b.code() #调用code方法,注意加括号
我会打代码
>>> b.wechat() #调用wechat方法,注意加括号
关注微信公众号'夜寒信息'
我们可以看出,Boy这个类完美的继承了Girl的属性和方法。
四、多态
多态指不同对象对同一方法响应不同的行动,例如男生见到夜寒哥哥会说“这个人很帅”,而女生见到夜寒哥哥会说“夜寒哥哥好帅,好想嫁给他”,同样是说,两种人说的话却是不同的。
下面我们举个例子
class Boysee: #新建一个Boysee类
def say(self): #定义say方法
print("这个人很帅")
class Girlsee: #新建一个Girlsee类
def say(self): #定义say方法
print("夜寒哥哥好帅,好想嫁给他")
下面我们来将他运行实现
>>> b = Boysee() #将类实例化
>>> g = Girlsee() #将类实例化
>>> b.say()
这个人很帅
>>> g.say()
夜寒哥哥好帅,好想嫁给他
由此我们看出,同样都调用了say方法,却输出了不同的结果,这就叫多态。
第二讲:
一、self
可能大家发现了之前在定义方法的时候,括号里都有一个self,那么什么是self呢?self就相当于是一个指针,当方法被调用时,self会传给类一个信号,让他知道是哪个方法被调用了。self就相当于在调用方法时,被调用的方法大喊,“是我(self)“,如果它不喊”是我(self)”,也就是不写self,那么调用时就不知道该传谁的方法了。
下面我们举个例子
class Love:
def setName(self,name): #在传入self的同时还传入了name变量
self.name = name #赋值
def say(self):
print("我叫{}我喜欢夜寒哥哥".format(self.name))
下面我们来运行上面的代码
>>> a = Love()
>>> b = Love()
>>> a.setName('小红') #调用setName方法,赋值给name
>>> b.setName('小橙') #调用setName方法,赋值给name
>>> a.say()
我叫小红我喜欢夜寒哥哥
>>> b.say()
我叫小橙我喜欢夜寒哥哥
我们在调用同一个say()方法时得到的是不同的结果,这就是因为被调用时,self.name被返回,打印到了屏幕上。由此我们可以更深的理解self的含义和用法
二、__init__方法
__init__方法为构造方法,在实例化一个对象的时候,这个方法会在创建方法时调用。在实例化对象时,是可以传入参数的,这些参数会自动传入到__init__方法中,我们可以重写__init__方法,来自定义对象的初始化参数。
下面我们来举个例子
class Love:
def __init__(self,name): #重写init方法,新加name变量
self.name = name
def say(self):
print("我叫{}我喜欢夜寒哥哥".format(self.name))
下面我们来运行这个代码
>>> l = Love('小红') #传入name的数据'小红'
>>> l.say()
我叫小红我喜欢夜寒哥哥
我们发现,我们传参数不需要再使用setName()方法,只需要在实例化对象时传入参数即可,若不传入参数则会报错
三、公有和私有
我们在定义变量的时候,默认所有的变量都是公有的,可以直接被查看的,例如之前Girl的例子,我们可以直接用g.look查看他的属性“可爱”,如果我们要将他变为私有变量,则只需要在他前面加上双下划线"__"即可
下面来举个例子
class Love:
__name = '小红' #将name变为私有变量
def say(self):
print("我叫{}我喜欢夜寒哥哥".format(self.__name))
>>> l = Love()
>>> l.say() #用方法正常调用
我叫小红我喜欢夜寒哥哥
>>> l.name #当我们尝试打印name变量的内容
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
l.name #报错,查找不到该变量
AttributeError: 'Love' object has no attribute 'name'
>>> l.__name #当我们尝试打印__name变量的内容
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
l.__name #报错,查找不到该变量
AttributeError: 'Love' object has no attribute '__name'
这样我们就可以看出私有的含义。顺带一提,Python中的私有是伪似有,只是将变量名悄悄更改了,我们可以通过使用<对象>._<类名>__<变量名>打印出实际数据,例如:
>>> l._Love__name
'小红' #成功打印
第三讲
一、继承
这一讲我们来仔细讲解一下继承。首先我们需要了解以下继承的写法。
class <子类名>(<父类名>)
&rmsp; 被继承的类我们把他称作父类,新建的类我们把它叫做子类,子类可以使用父类的所有属性和方法,同时也可以新定义自己的方法和属性。这些我们在第一讲介绍过了,就不再赘述。值得一提的是,如果子类新建了与父类同名的方法则会覆盖掉父类同名的方法,但父类不受影响。
下面我们来举一个例子
import random as r #引入随机数的库
class Skate: #新建一个滑板的类
def __init__(self): #重写init方法
self.temp = r.randint(0, 1)
def treflip(self):
print("我出了%d个大乱"% self.temp)
class Pjj (Skate): #继承滑板父类
pass
class Yh (Skate): #继承滑板父类
def __init__(self):
super().__init__() #supe()r函数,稍后讲解
self.judge = False
def say (self): #判断是否作出大乱
if self.judge:
print("我夜寒也会大乱")
else:
print("大乱太简单了,没意思")
self.judge = True
上面我们定义了一个滑板的类,在实例化对象时会传入一个随机数判断出了几个大乱(0或1)。下面的Pjj继承了Skate的类,Yh也继承了Skate的类同时作出了一点调整,加入了方法say判断夜寒是否出大乱。
下面我们运行这个代码
>>> p = Pjj() #实例化参数
>>> p.treflip()
我出了1个大乱
>>> y=Yh()
>>> y.treflip()
我出了0个大乱
>>> y.say()
大乱太简单了,没意思
>>> y.say()
我夜寒也会大乱
我们可以看到,两个人的类都可以使用滑板作招的类,这就是缘于继承。这里讲解一下super()函数,我们可以看到我们在定义Yh的类时重写了父类的__init__方法,这会导致方法被覆盖,于是我们使用了super函数来引入需要的父类的方法,用法super().<方法名>()
二、多重继承
从字面就可以看出,多重继承指,一个子类继承多个父类,使用方式<子类名>(父类1, 父类2, …)
下面举个例子
class C1: #父类1
def M1(self):
print("我是父类1")
class C2: #父类2
def M2(self):
print("我是父类2")
class C3(C1, C2): #多重继承的子类3
def M3(self):
print("我是子类")
下面我们运行这段代码:
>>> c1=C1()
>>> c2=C2()
>>> c3=C3()
>>> c3.M1()
我是父类1
>>> c3.M2()
我是父类2
>>> c3.M3()
我是子类
>>> c3.M1()
我是父类1
>>> c3.M2()
我是父类2
这样我们就能看出子类C3可以使用多个父类的方法。
四、组合
在我们编程时会遇到需要定义的几个关系不是很明确的类,使用继承会奇怪,这时候便需要组合。这么说恒难理解,下面我们来举个例子。
class Yh:
def __init__(self,x):
self.num = x
class Pjj:
def __init__(self,x):
self.num = x
class Ground:
def __init__(self,m,n):
self.yh = Yh(m) #使用组合
self.pjj = Pjj(n)
def count(self):
print('场地里有%d个潘家杰,%d个夜寒'%(self.yh.num,self.pjj.num))
组合就是把类的实例化的对象放到一个新的类里,这就是组合,(个人觉得可以按照自递归理解)。
然后我们来运行这段代码
>>> g = Ground(1, 1)
>>> g.count()
场地里有1个潘家杰,1个夜寒
五、一些相关的BIF
issubclass(class, classinfo)
检查class是不是classinfo的子类,注意:自身可以是自身的子类,classinfo也可以是个元组
isinstance(object, classinfo)
检查object是不是classinfo的实例对象,注意:如果object传入的不是object类型则会显示False,若classinfo传入的不是class类型则会报TypeError错误。
hasattr(object, name)
测试object是否有名为name的属性。例:
>>> class A:
def __init__(self, x=0):
self.x = x
>>> a=A()
>>> hasattr(a, 'x') #测试x是否为a内的属性
True
getattr(object, name, default)
测试object是否有名为name的属性,如果有返回True,否则返回Default的值。例:
>>> class A:
def __init__(self, x=0):
self.x = x
>>> getattr(a, 'y', '没有') #测试y是否为a的属性
setattr(object, name ,value)
设置对象(object)中指定属性(name)的值(value),若无指定属性,新建一个属性。例:
>>> class A:
def __init__(self, x=0):
self.x = x
>>> getattr(a, 'y', '没有')
'没有'
>>> setattr(a, 'y', '夜寒信息')
>>> getattr(a, 'y', '没有')
'夜寒信息'
dekattr(object, name)
删除对象中指定属性,若属性不存在产生AttributeError,例:
>>> class A:
def __init__(self, x=0):
self.x = x
>>> delattr(a, 'y')
>>> delattr(a, 'y')
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
delattr(a, 'y')
AttributeError: y
property(fget, fest, fdel, doc)
通过属性来设置属性,例:
>>> class Y:
def __init__(self, yh = '夜寒信息'):
self.yh = yh
def getYh(self):
return self.yh
def setYh(self, value):
self.yh = value
def delYh(self):
del self.yh
w = property(getYh, setYh, delYh)
>>> y = Y()
>>> y.getYh()
'夜寒信息'
>>> y.w
'夜寒信息'
>>> y.w = '欢迎关注夜寒信息'
>>> y.w
'欢迎关注夜寒信息'
>>> del y.w
>>> y.w
Traceback (most recent call last):
File "<pyshell#49>", line 1, in <module>
y.w
File "<pyshell#42>", line 5, in getYh
return self.yh
AttributeError: 'Y' object has no attribute 'yh'
这样我们可以看出,我们只需要更改w的属性便可以更改类的属性,fget为获取属性的方法,fset为设置属性的方法,fdel为删除属性的方法。
致力于为每一位用户免费提供更优质技术帮助与资源供给,感谢支持!