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为删除属性的方法。



致力于为每一位用户免费提供更优质技术帮助与资源供给,感谢支持!