Python 快速了解面向对象

时间:2020-8-24 作者:admin


python面向对象

1.python 面向对象概念

面向对象是程序设计封装的一种思想 ! ! !

1,列表是将各种不同的数据类型的数据封装到一个容器里面 --> 数据层面的封装 

2,函数是将一段代码封装到一起 --> 语句层面的封装 

3,面向对象是将具有相同属性和方法的代码封装到一起 --> 程序设计层面的封装

那么 为什么要用面向对象呢?

面向对象的好处:拓展性强,比方王者荣耀新增一个英雄很方便。
解耦和,降低程序的维护成本

2. 类和对象

2.1 类的概念(class)

类是模板,具有相同特征和行为的一类事务。
比如说王者荣耀里面的 射手类  法师类 战士类 刺客类等等

2.2 对象的概念

对象是一个由具体产生的实例,比方说:射手类-->鲁班,法师类-->妲己

写在类里面的函数称之为方法

例如 定义一个射手类

class sheshou:
	"""射手类"""
	#类的属性(一般指的是变量)
	gongji = 1700  #攻击力
	fangyu = 300 防御力
	
   #行为(实例方法)
   def  sheji(self)
   		print("我的攻击力是:{},防御能力是:{}".format(self.gongji,self.fanyu))

luban = Sheshou() #实例化,将类实例化出一个具体的对象,由射手类创建出一个鲁班对象 

print(luban) #打印出来的是一个地址,通过这个地址可以找到luban这个对象

luban.sheJi() #通过对象去调用方法 

houyi = Sheshou() #创建一个后裔 

houyi.sheJi()  #用这个实例出来的后裔对象 去调用sheji方法
   		
#Sheshou.sheJi() #实例方法不能直接通过类去调用 
# luban = Sheshou() #实例方法可以通过实例对象去调用 
# luban.sheJi()

2.3 初始化方法

初始化方法是魔术方法之一, 所谓魔术方法就是在符合一定条件可以自动调用

class Sheshou:
		 """射手类""" 
		 def __init__(self):	#初始化方法(魔术方法)
		 	 print("今天是个好日子") 

luban = Sheshou() #实例化的过程就是这个类初始化的过程
#在实例化的时候 这个初始化的魔术方法会自动调用

2.4 实例方法(普通方法)

实例方法,会隐含一个self参数,实例方法不属于类,属于实例。通过实例对象才能调用。
不能直接通过类去调用.

class Sheshou:
		 """射手类""" 
		 #行为(实例方法) 
		 def sheJi(self): 
		 	print("我的攻击力是:{},防御能力是:{}".format(self.gongji,self.fanyu))

#只有实例化一个对象 才可以通过那个对象去调用实例方法

3. 类属性和实例属性

3.1 类属性

类属性是直接定义在类里面的变量,属于类本身。可以去访问它也可以去修改它

class Sheshou: 
	"""射手类""" 
	
	#类属性(变量)
	 gongji = 1700 #攻击力 
	 fanyu = 300 #防御力 

 print(Sheshou.gongji) #访问 
 Sheshou.gongji = 1500 #修改 
 print(Sheshou.gongji)
 #类属性可以之间通过类进行访问修改

3.2 实例属性

实例属性不是直接定义在类的里面,通过初始化方法注入到类里面

class Sheshou: 
	"""射手类"""
	def __init__(self,gongji,fangyu):
		#初始化方法(魔术方法) 
		self.gongji = gongji #实例属性 
		self.fangyu = fangyu #实例属性 
		print("今天是个好日子") 

print(Sheshou.gongji) #会报错 实例化属性不能直接通过类名去调用,必须通过实例化才能够访问它,修改它 

#你得先实例一个对象出来 再通过实例对象去调用实例属性

3.3 深度剖析 self

class Sheshou:
	 """射手类""" 
	 #所谓魔术方法就是在符合一定条件可以自动调用 
	 def __init__(self,gongji,fangyu):#初始化方法(魔术方法)
	 	 self.gongji = gongji #实例属性 
	 	 self.fangyu = fangyu #实例属性 
	 	 print("self是:{}".format(self)) 

luban = Sheshou(1200,100) 
print("luban是:{}".format(luban)) print("\n====================================================\n") 
houyi = Sheshou(600,180) 
print("houyi是:{}".format(houyi)) 
#充足的证据证明self就是当前对象,当前实例化的对象是谁,那么self就指向谁
#当生成luban这个对象的时候 self当前就指向luban
#当生成houyi这个对象的时候 self当前就指向houyi

4. 类方法

类方法属于类,不会隐含self,会隐含一个cls。
类方法需要使用@classmethod装饰器来进行修饰。
类方法可以直接通过类去调用,也可以被实例化对象调用。

class Cat:
	 """猫类"""
	  def __init__(self,nickname,color): 
	  	self.nickname = nickname 
	  	self.color = color 
	  	
		@classmethod #@classmethod是一个装饰器,作用就是为这个方法添加一个额外的功能
		def zhuaLaoShu(cls): 
		print("抓老鼠") 

#直接通过类名调用 
Cat.zhuaLaoShu()  #会被成功调用,因为调用的对象是一个类方法 ,可以通过类进行直接调用
问题:类方法中能不能使用实例属性?
答案肯定是:不能。
# 原因:类方法的加载不需要实例化,初始化方法没有被调用。 实例属性就没来得及注入

4.1 静态方法

静态方法需要使用@staticmethod来修饰
静态方法没有隐含任何参数,既可以实例化后通过对象去调用, 也可以直接被类调用。

静态方法不能访问类变量和实例变量,也不能使用self 要在类中使用静态方法,需在类成员函数前面加上@staticmethod标记符,以表示下面的成员函数是静态函 数。

使用静态方法的好处是,不需要定义实例即可使用这个方法。另外,多个实例共享此静态方法

(静态方法 无法访问类属性、实例属性,相当于一个相对独立的方法,跟类其实没什么关系,简单讲,静态方法就是放在 一个类的作用域里的函数而已。

静态方法的应用:抽取工具类

接下来请看如下案例:
我们先用面向对象写一个人机猜拳的游戏:

用户类:
class User: 
	"""用户类""" 
	#初始化方法,在实例化的时候自动调用 
	def __init__(self,userName): 
		self.userName = userName 

   	#实例方法(普通方法) 
   	def chuZhao(self): 
   		uz = int(input("亲爱的{},请出招(1-剪刀 2-石头 3- 布):".format(self.userName))) 
   		if uz == 1:
   			print("{}出招:剪刀".format(self.userName)) 
   		elif uz == 2: 
   			print("{}出招:石头".format(self.userName))
   		else:
   			print("{}出招:布".format(self.userName)) 
   		return uz
电脑类:
class Computer:
	 """用户类""" 
	 # 初始化方法,在实例化的时候自动调用 
	 def __init__(self, nickName): 
	 	self.nickName = nickName # 实例方法(普通方法) 

	 def chuZhao(self): 
	 	import random cz = random.randint(1,3)     #这边利用一个随机函数 随机生成(1-3)
	 	if cz == 1: 
	 		print("{}出招:剪刀".format(self.nickName)) 
	 	elif cz == 2: 
	 		print("{}出招:石头".format(self.nickName)) 
	 	else:
	 		print("{}出招:布".format(self.nickName)) 
	 	return cz
进行比较:
from oop.人机猜拳.用户 import * 
from oop.人机猜拳.电脑 import * 

zs = User("小张") #实例化 
xa = Computer("小爱同学") #实例化 

u = zs.chuZhao() #通过对象去调用实例化方法 
c = xa.chuZhao() #通过对象去调用实例化方法 

if u == c: 
	print("平局") 
elif u == 1 and c == 3 or u == 2 and c == 1 or u == 3 and c == 2: 
	print("{}胜利!".format(zs.userName)) 
else:
	print("{}胜利!".format(xa.nickName))
这边我门可以利用静态方法去进行一个抽取
抽取出一个工具类
如上所述:
我们可以看到上诉代码有一些重复性的区域

这边进行一个抽取工具类的操作

工具类:

class Utils: 
	@staticmethod 
	def zhaoShi(name,zhao): 
		if zhao == 1: 
			print("{}出招:剪刀".format(name)) 
		elif zhao == 2: 
			print("{}出招:石头".format(name)) 
		else:
			print("{}出招:布".format(name))

用户类:
from oop.人机猜拳.工具类 import * 
	class User:
	 """用户类""" 

	 #初始化方法,在实例化的时候自动调用 
	 def __init__(self,userName): 	
	 	self.userName = userName 

  	#实例方法(普通方法) 
  	def chuZhao(self): 
  		uz = int(input("亲爱的{},请出招(1-剪刀 2-石头 3- 布):".format(self.userName))) 
  		Utils.zhaoShi(self.userName,uz)     #在此调用工具类的方法
  		return uz

电脑类:
from oop.人机猜拳.工具类 import * 
class Computer: 
	"""用户类""" 
	# 初始化方法,在实例化的时候自动调用 
	def __init__(self, nickName): 
		self.nickName = nickName
	# 实例方法(普通方法) 
	def chuZhao(self): 
		import random cz = random.randint(1,3) 
		Utils.zhaoShi(self.nickName,cz)     #在此调用工具类的方法
		return cz

对比类:
from oop.人机猜拳.用户 import * 
from oop.人机猜拳.电脑 import * 
zs = User("小张") #实例化 
xa = Computer("小爱同学") #实例化 

u = zs.chuZhao() #通过对象去调用实例化方法 
c = xa.chuZhao() #通过对象去调用实例化方法 

if u == c: 
	print("平局") 
elif u == 1 and c == 3 or u == 2 and c == 1 or u == 3 and c == 2: 
	print("{}胜利!".format(zs.userName)) 
else:
	print("{}胜利!".format(xa.nickName))

5. 面向对象的特征

5.1 封装

封装的概念

将类的属性或者方法私有化,不让外界直接访问,对外提供一个访问的接口。
提高数据的安全性。不用去管类 的具体细节,就可以获取类的实现接口,提高了开发的效率。

将类私有化!!!
只用在类属性或方法前加上__(两个下横杠即可)

class Woman:
	 """女人类"""
	  #常识:女生的年龄是不能随意访问的 
	  def __init__(self,name,age,weight): 
	  	self.name = name #姓名 
	  	self.__age = age #年龄 #私有化 
	  	self.weight = weight #体重
	  	
	  def show(self): print("我的名字叫:{},年芳:{},体重:斤".format(self.name,self.__age,self.weight)) 

binbin = Woman("冰冰",18,120)
 #binbin.age = 190 #不能通过对象随意访问属性,数据不安全 
 binbin.age = 150 #私有化后,就不能随意访问和修改 
 binbin.name = "小凤" 
 binbin.show()

5.2 对外提供访问的接口

class Woman: 
	"""女人类""" 
	#常识:女生的年龄是不能随意访问的 
	def __init__(self,name,age,weight): 
		self.name = name #姓名
		self.__age = age #年龄 私有化 
		self.weight = weight #体重 

	 #定义set和get方法,是一个外界可以访问的接口 
	 def setAge(self,age):#设置 
	 #可以在这个方法里面加上业务逻辑,可以起到保护数据安全的作用 
	 	if age > 120 or age < 0: 
	 		age = 18 
	 		print("年龄不合法!年龄将自动设置为18岁") 
	 	else:
	 		self.__age = age

		def getAge(self): #定义一个获取 方法
			return self.__age 
		
		def show(self): 
			print("我的名字叫:{},年芳:{},体重:{} 斤".format(self.name,self.getAge(),self.weight)) binbin = Woman("冰冰",18,120) 

#binbin.age = 190 #不能通过对象随意访问属性,数据不安全
#binbin.age = 150 #私有化后,就不能随意访问和修改 
binbin.name = "小凤" 

binbin.setAge(220) #可以通过指定的接口访问
binbin.show()


#这边通过一个指定的 setAge()的接口 去获取年龄数据
再通过getAge()去返回一个年龄

5.3 继承

子类继承父类,子类可以拥有父类的所有属性及所有方法。
这样可以大大提高代码的复用性。 java只支持单继承,或者是多层继承。 python支持多继承,多层继承

5.31 单继承

class Animal: 
	"""动物类""" 
	def __init__(self,name,sex): 
	self.name = name 
	self.sex = sex 
	
	def eat(self): 
	print("{}吃饭,性别:{}".format(self.name,self.sex)) 
	
	def drink(self): 
	print("喝") 

class Cat(Animal):    #继承动物类
	pass 

class Dog(Animal):     #继承动物类
	pass 

c = Cat("小肥猫","雌")     #父类拥有的方法 子类也拥有
c.eat()                             #通过子类去调用父类的方法
d = Dog("旺财","雄") 
d.eat()

5.32 多继承

class Animal: 
	"""动物类""" 
	def __init__(self,name,sex): 
		self.name = name 
		self.sex = sex 
		def eat(self): 
			print("{}吃饭,性别:{}".format(self.name,self.sex)) 
    	def drink(self): 
    		print("喝") 

class People: 
	def sing(self): 
		print("唱歌") 

class Cat(Animal,People):   #同时继承动物类 和People类
	pass 
class Dog(Animal,People):    #同时继承动物类 和People类
	pass 

c = Cat("小肥猫","雌") 
c.sing() 
c.eat() 

d = Dog("旺财","雄") 
d.sing() 
d.eat()

5.4 子类重写父类的方法

如果子类有一个与父类名相同的方法,则这个方法会被子类重写

class Animal:
	"""动物类"""
	def drink(self): 
		print("喝")

class fish(Animal):
	"""鱼类"""
	def drink(self):      #子类重写父类的方法,父类的方法会被子类的方法覆盖
		print("喝水")

c = fish()
c.drink()
#结果为喝水

5.5 子类不想重写父类方法 只想扩展

class Animal:
	"""动物类"""
	def drink(self): 
		print("喝")

class fish(Animal):
	"""鱼类"""
	def drink(self):    
		super().drink() #子类拓展父类的方法,不会完全覆盖父类的方法,保留父类方法的同时,拓展 自己的业务
		print("喝水")

这时候只需要加上一句 super()就行,这样子类只会扩展,而不会重写

5.6 多态

多态的定义:不同的子类对象调用相同的方法产生不同的执行结果

多态使用前提:需要继承和对父类方法进行重写

多态的作用:一种接口多种实现,实现接口的重用

实现多态的步骤:
1,定义新的子类继承父类
2,重写对应的父类方法
3,使用子类的方法直接处理,不调用父类的方法

总结:不同的子类对象 使用同一个方法 结果输出需要的执行结果 -- 父类引用指向子类对象
在学校,铃声响起的时候,对于学生来说是放学,对于老师是下班
class School: 
	"""学校""" 
		def music(self): 
			print("打铃")

class Student(School): 
	def music(self): 
		print("铃声响起,放学了") 

class Teacher(School): 
	def music(self): 
		print("铃声响起,下班了") 

s = Student() #实例化出一个学生对象 
t = Teacher() #实例化一个老师出来 

def jiekou(obj): #传入学生对象,实现学生的业务。传入老师,实现老师的业务。同一个接口,不同实现 
	obj.music() 

jiekou(t)  #通过不同的参数 产生不同的结果 #传入老师 就是老师的music()方法 
#传入学生 就是学生的music()的方法
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。