zoukankan      html  css  js  c++  java
  • Python面向对象基本特征

    面向对象基本特征

    封装

    封装是指对外界隐藏信息,不能随意访问、修改对象的数据和方法

    封装是通过限制类的属性和方法的访问方式来实现的封装效果

    封装的三个层次:

    1. 类的封装:外部可以任意访问、修改类中的属性和方法
    2. 私有属性:外部不可以访问、修改勒种的属性和方法
    3. 公有方法+私有属性:外部有条件限制的访问、修改属性,调用方法

    封装表现1:

    类的定义:将某些特定属性和方法进行“隔离”

    每个学生有自己的年龄,外部可以任意读取或者修改

    class Student:
    
    	def __init__(self,name,age):
    		self.name = name
    		self.age = age
    
    s1 = Student("李白",18)
    s2 = Student("杜甫",20)
    s2.age = 200
    print(s1.name)
    print(s2.age)
    

    封装表现2:

    属性私有:只能在类的内部使用,外部不能使用

    不让外部读取、修改学生的年龄

    class Student:
    
    	def __init__(self,name,age):
    		self.name = name
    		self.__age = age	#使用两个下划线开头的属性,定义为私有属性
    		print(self.__age)
    
    	__secret = True  
    
    s1 = Student("李白",18)
    # print(s1.__age)		#外界无法直接通过属性名称来访问
    #虽然语法可以在外部通过_Student__age访问到私有属性,但是不推荐使用
    print(s1._Student__age)
    
    #__dict__查看当前对象或者类有哪些属性
    print(s1.__dict__)
    print(Student.__dict__)
    

    封装表现3:

    私有属性+ 公有方法:有限制条件的开放给外部

    可以读取年龄,但不能随意修改年龄

    设定年龄必须在(1,125)之间

    class Student:
    
    	def __init__(self,name,age):
    		self.name = name
    		self.__age = age
    
    	def getAge(self):
    		return self.__age
    
    	def setAge(self,age):
    		if 0 < age < 125:
    			self.__age = age
    		else:
    			print("年龄不符合人类")
    s1 = Student("李白",18)
    print(s1.getAge())
    s1.setAge(200)
    print(s1.getAge())
    

    私有方法

    可以在类的内部使用,有条件的开放给外部

    class Person:
    	def __tellSercert__(self):
    		print("夏天夏天悄悄过去,留下小秘密~~~~")
    
    	def talk(self,object):
    		if object == "好基友":
    			self.__tellSercert__()
    		else:
    			print("我是一个木得感情木得秘密的人")
    
    ming = Person()
    ming.talk("好基友")
    ming.talk("隔壁小黑")
    

    封装的简化写法

    装饰器

    property装饰器:把一个方法伪装成一个属性,在调用这个方法的时候不需要加()就可以直接得到返回值

    class Dog:
    
    	@property			#装饰器
    	def bark(self):
    		print("旺旺旺~~~")
    		return 89757
    
    d = Dog()
    
    num = d.bark  #注意这里没有括号呦
    print(num)
    

    总结

    使用@property装饰器时,方法名不必与属性名相同

    可以更好的防止外部通过猜测私有属性名称来访问

    凡是赋值语句就会触发set方法,获取属性值会触发get方法

    继承

    面临的问题:

    • 相似类型的定义会产生大量重复的代码
    • 类的定义没有很好的扩展性‘

    解决的方法:

    定义类和类之间的关系,子类拥有父类的全部属性和方法,并可以为之扩充

    示例

    class Pet:
    
    	def __init__(self,name,age):
    		self.name = name
    		self.age = age
    		print(f"一只名字叫{self.name}的宠物出生了")
    
    	def eat(self):
    		print(f"{self.name}在吃东西~~~")
    
    	def run(self):
    		print(f"{self.name}在溜达~~~")
    
    
    class Dog(Pet):
    	pass
    
    
    class Cat(Pet):
    	pass
    
    d = Dog("咯咯",3)
    d.run()
    
    c = Cat("布丁",1)
    c.eat()
    

    1.继承的概念:

    • Dog和Cat继承了Pet类
    • Dog和Cat称为Pet的子类、派生类
    • Pet称为Dog和Cat的父类、超类、基类
    • 子类默认拥有父类公有的属性和方法的定义

    2.子类调用方法的顺序

    • 调用方法时,子类中有的,调用子类中的
    • 子类中没有的,调用父类的
    • 一旦在子类中找到,就不在去父类中查找了
    子类不能继承父类的私有属性或者方法
    class Father:
    	__secret = "小秘密"
    	story = "从前有座山,山上有座庙"
    
    	def tellStory(self):
    		print(self.story)
    
    	def __tellSecret(self):
    		print(self.__secret)
    
    class Son(Father):
    	def tell(self):
    		# self.tellStory()
    		self.__tellSecret()
    s = Son()
    s.tell()
    

    3.重写/覆盖

    • 子类和父类拥有相同名称的方法
    • 可以理解为子类对于父类行为的扩展和补充
    class Pet:
    	master = True
    
    	def __init__(self,name,age):
    		self.name = name
    		self.age = age
    		print(f"一只名字叫{self.name}的宠物出生了")
    
    	def eat(self):
    		print(f"{self.name}在吃东西~~~")
    
    	def run(self):
    		print(f"{self.name}在溜达~~~")
    
    
    class Dog(Pet):
    	#重写父类方法
    	def eat(self):
    		print(f"{self.name}在啃骨头")
    	#扩充,定义子类特有功能
    	def lookAfter(self):
    		print(f"{self.name}在看门,汪汪汪!")
    
    d = Dog("旺财",2)
    d.eat()
    d.lookAfter()
    

    4.子类可以在类定义时,可以使用super()调用父类的方法

    应用1:和重写不同,重写是对父类方法的完全覆盖,这是对父类方法的补充
    class Pet:
    	def __init__(self,name,age):
    		self.name = name
    		self.age = age
    		print(f"一只名字叫{self.name}的宠物出生了")
    
    	def eat(self):
    		print(f"{self.name}在吃东西~~~")
    
    	def run(self):
    		print(f"{self.name}在溜达~~~")
    
    
    class Cat(Pet):
    
    	def eat(self):
    		print(f"{self.name}伸了个懒腰")
    		super().eat()
    		print(f"{self.name}吃完东西后,舔了舔爪子")
    
    c = Cat("布丁",2)
    c.eat()
    
    应用2:对象初始化时,简化重复属性的赋值
    class Cat(Pet):
    
    	def __init__(self,name,age,sex):
    		# self.name = name
    		# print(f"一只名叫{self.name}的宠物出生了")
    		super().__init__(name)		#代替了上两句代码,简化了重复属性的赋值
    		self.age = age
    		self.sex = sex
    

    5.多继承

    • 子类可以有多个父类
    • 例如:狗是脊椎动物,哺乳动物,宠物。。。
    class Father:
    	caihua = "有才"
    
    
    class Mother:
    	yanzhi = "有貌"
    
    
    class Child(Father,Mother):
    	pass
    
    c = Child()
    print(c.caihua,c.yanzhi)
    
    print(Child.__bases__)		#可以通过类名.__bases__查看其父类
    

    6.访问子类的属性或者方法时,解析的路径(顺序)

    class Father:
    	def getMoney(self):
    		print("爸爸给了零花钱")
    
    class Mother:
    	def getMoney(self):
    		print("妈妈给了零花钱")
    
    class Child(Father,Mother):
    	def getMoney(self):
    		super().getMoney()	
    		#按照继承的顺序查找父类中的方法,所以先找Father类
    		print("孩子获得了零花钱")
    
    c = Child()
    c.getMoney()
    

    从第一个父类开始向上查找,直到查找结束都没有,再对第二个父类进行查找

    深度优先:Child -> Father -> GrandFather -> Mother

    class GrandFather:
    	pass
    	# def getMoney(self):
    	# 	print("爷爷给了零花钱")
    
    class Father(GrandFather):
    	pass
    	# def getMoney(self):
    	# 	print("爸爸给了零花钱")
    
    class Mother:
    	def getMoney(self):
    		print("妈妈给了零花钱")
    
    class Child(Father,Mother):
    	def getMoney(self):
    		super().getMoney()
    		#按照继承的顺序查找父类中的方法,所以先找Father类
    		print("孩子获得了零花钱")
    
    c = Child()
    c.getMoney()
    print(Child.mro())		#可以通过类名.mro()的方式来查看类的解析顺序
    
    • object是所有类的父类
    • “万事万物”皆为对象,因为所有的类都默认继承object

    7.菱形继承

    image-20201118083544047

    广度优先:Child -> Father -> Mother -> Human

    image-20201118084332241

    多态

    想要解决的问题

    • 让程序能够有更强的灵活性
    • 让程序能够有更好的适应性
    • 概念:一个类的多种形态

    情况1:通过继承和重写来实现

    class Animal:
    	def eating(self):
    		print("动物在吃东西")
    
    
    class Pet(Animal):
    	def eating(self):
    		print("宠物在吃东西")
    
    class Dog(Pet):
    	def eating(self):
    		print("狗在啃骨头~")
    
    class Cat(Pet):
    	def eating(self):
    		print("小猫在吃鱼")
    
    class Zoo:
    	def animalEating(self,animal):
    		animal.eating()
    
    z = Zoo()
    a = Animal()
    p = Pet()
    d = Dog()
    c = Cat()
    #Dog和Cat都作为Animal的不同形态
    #都可以直接调用animal所具有的属性和方法
    z.animalEating(a)
    z.animalEating(p)
    z.animalEating(d)
    z.animalEating(c)
    

    情况2:Python持有

    没有继承关系,但是也具备相同的特征、方法,也可以直接使用

    class venusFlytrap:		#捕蝇草
    	def eating(self):
    		print("捕蝇草在吃小虫子")
    
    
    v = venusFlytrap()
    z.animalEating(v)
    

    捕蝇草不继承于Animal类,但是具有和它相同的特征,在python只要具有相同的特征和方法,没有继承关系也可以直接使用

    type和isinstance

    #type判断类型时,只看直接类型
    print(type(c) is Cat)		#True
    print(type(c) is Animal)	#False
    print(type(c) is Pet)	#False
    #isinstance 判断对象是否为一个类型的实例
    #判断实例类型时,涵盖父类的类型
    print(isinstance(c,Cat))	#True
    print(isinstance(c,Pet))	#True
    print(isinstance(c,Animal))	#True
    print(isinstance(venusFlytrap,Animal))	#False
    
  • 相关阅读:
    word设置的密码忘了怎么办?
    Navicat Report Viewer 设置 HTTP 的方法
    如何处理Navicat Report Viewer 报表
    excel密码忘记了怎么办
    Beyond Compare文本比较搜索功能详解
    Popular Cows POJ
    Problem B. Harvest of Apples HDU
    网络流模型整理
    The Shortest Statement CodeForces
    Vasya and Multisets CodeForces
  • 原文地址:https://www.cnblogs.com/icyhblog/p/14068282.html
Copyright © 2011-2022 走看看