zoukankan      html  css  js  c++  java
  • 面向对象编程学习笔记

    面向对象的编程

    面向过程的编程:
    • 核心:过程(过程指的是解决问题的步骤,机械式的思维方式)
    • 优点:将复杂的问题流程化,进而简单化
    • 缺点:可扩展性差
    面向对象编程
    • 核心:对象(对象就是特征与技能的结合体)
    • 对象:python中一切是对象
    • 优点:可扩展性强
    • 缺点:编程复杂度高
    • 应用场景:用户需求经常变化,互联网应用,游戏,企业内部应用
    • 类:就是一 系列对象相似的特征与技能的结合体(站在不同角度,得到的分类是不同的)
    • 对象:特征与技能结合体
    • 在现实世界中:一定先有对象,后有类
    • 在程序中:一定得先定义类,后调用类来产生对象
    • 查看名称空间:
    stu1 = LufftStudent()
    print(stu1.__dict__)
    

    类:

    class LuffyStudent:
    	school = 'luffycity' #数据属性
    	
    	def learn(self):# 函数属性
    		print('is learing')
    	
    	def eat(self):
    		print('is eating')
    		
    		
    stu1 = LuffyStudent() #实例化对象
    
    
    # # 查看类的名称空间
    # print(LuffyStudent.__dict__)
    # print(LuffyStudent.__dict__['school'])
    # print(LuffyStudent.__dict__['learn'])
    
    # 查看类的属性
    #print(LuffyStudent.school) #LuffyStudent.__dict__['school']
    
    # 增加类的属性
    LuffyStudent.county = 'China'
    
    # 删除
    del LuffyStudent.county
    
    # 改
    LuffyStudent.school = 'Luffycity'
    
    
    __init__方法
    class LuffyStudent:
    	school = 'luffycity' #数据属性
    	def __init__(self,name,sex,age):# __init__方法用来对象定制对象独有的特征
    		self.Name = name
    		self.Sex = sex
    		self.Age = age
    
    	def learn(self):# 函数属性
    		print('is learing')
    
    	def eat(self):
    		print('is eating')
    
    # 后产生的对象
    stu1 = LuffyStudent('wualin','man',29)#LuffyStudent.__init__(stu1,'wualin','man',20)
    
    # 加上__init__方法后,实例化步骤
    # 1. 先产生一个空对象stu1
    # 2. 触发LuffyStudent.__init__(stu1,'wualin','man',29)
    
    #
    # # 查
    # print(stu1.Name)
    # print(stu1.Sex)
    # print(stu1.Age)
    # # 改
    # stu1.Name='520'
    #
    # # 删除
    # del stu1.Name
    #
    # # 增
    # stu1.class_name = 'python开发'
    
    属性查找
    • 类中的数据属性:是所有对象共有的

    • 类中的函数属性:是绑定给对象,绑定到不同的对象是不同的绑定方法,对象调用绑定方式时,会把对象本身当作第一个传入,传个self

    class LuffyStudent:
    	school = 'luffycity' #数据属性
    	def __init__(self,name,sex,age):# __init__方法用来对象定制对象独有的特征
    		self.Name = name
    		self.Sex = sex
    		self.Age = age
    
    	def learn(self):# 函数属性
    		print('is learing')
    
    	def eat(self):
    		print('is eating')
    
    # 后产生的对象
    stu1 = LuffyStudent('wualin','man',29)
    stu2 = LuffyStudent('张宝宝','man',19)
    
    # 类的数据属性
    print(stu1.school)
    
    
    # 类的函数属性,类中函数属性是给对象使用的,谁调用就绑定给它使用,自动将对象传入第一个参数
    
    
    stu1.learn()#learn(stu1)
    
    #对象在访问一个属性的时候会先在对象里面的名称空间找,如果对象里面没有则去类里面找。不会到全局变量里面找
    
    python中一切皆对象:
    • 对象之间的交互:
    class Girlun:
    	faction = 'Demasia'
    	def __init__(self,name,life,attack):
    		self.name = name
    		self.life = life
    		self.attack = attack
    	def attack_1(self,enemy):
    		enemy.life = enemy.life-self.attack
    		print('%s攻击了%s'%(self.name,enemy.name))
    
    
    class Riwen:
    	faction = 'Demasia'
    
    	def __init__(self, name, life, attack):
    		self.name = name
    		self.life = life
    		self.attack = attack
    
    	def attack_1(self, enemy):
    		enemy.life = enemy.life - self.attack
    		print('%s攻击了%s' % (self.name, enemy.name))
    g1 = Girlun('草丛伦',100,10)
    r1 = Riwen('锐萌萌',80,20)
    print(r1.life)
    g1.attack_1(r1)
    print(r1.life)
    

    继承与重用

    • 继承指的是类与类之间的关系
    • 查看继承自父类的哪些东西:
    print(<类名>.__bases__)
    
    • 继承示例:
    class Hero:
    	def __init__(self,name,life,attack):
    		self.name = name
    		self.life = life
    		self.attack = attack
    	def attack_1(self,enemy):
    		print('%s攻击了%s'%(self.name,enemy.name))
    
    class Griren(Hero):
    	pass
    
    class Riven(Hero):
    	pass
    
    g1 = Griren('盖伦',80,50)
    r1 = Riven('锐雯',50,50)
    
    g1.attack_1(r1)
    
    派生
    • 当子类中有需要的属性则不会去父类中查找
    继承的实现原理:
    • 原则:
      • 子类会先余父类被检查
      • 多个父类会根据他们在列表中的顺序被检查(从左到右)
      • 如果下一个类存在两个合法的选择,会选择第一个父类
    • MRO查找方法
    print(<类名>.__mro__
    
    在子类中重用父类的方法或属性
    • 方式一:指名道姓,类名+方法(不依赖继承)
    class Hero:
    	def __init__(self,name,life,attack):
    		self.name = name
    		self.life = life
    		self.attack = attack
    	def attack_1(self,enemy):
    		enemy.life -=self.attack
    
    class Griren(Hero):
    	def attack_1(self,enemy):
    		Hero.attack_1(self,enemy) # 不依赖于继承
    		print('%s攻击了%s'%(self.name,enemy.name))
    class Riven(Hero):
    	pass
    
    g1 = Griren('盖伦',80,50)
    r1 = Riven('锐雯',100,50)
    print(r1.life)
    g1.attack_1(r1)
    print(r1.life)
    
    • 方式二:super()
      • super()查找方法基于mro列表往后找
    class Hero:
    	def __init__(self,name,life,attack):
    		self.name = name
    		self.life = life
    		self.attack = attack
    	def attack_1(self,enemy):
    		enemy.life -=self.attack
    
    class Griren(Hero):
    
    	def __init__(self,name,life,attack,weapon):
    		super().__init__(name,life,attack)# 第一种写法,依赖于继承
    	def attack_1(self,enemy):
    		super(Griren,self).attack_1(enemy)# 第二种写法,依赖于继承
    		print('%s攻击了%s'%(self.name,enemy.name))
    class Riven(Hero):
    	pass
    
    g1 = Griren('盖伦',80,50,'大保健')
    r1 = Riven('锐雯',100,50)
    print(r1.life)
    g1.attack_1(r1)
    print(r1.life)
    print(g1.__dict__)
    
    组合
    • 将两个类生成的实例对象组合在一起
    抽象类与归一化
    • 通过抽象类使子类中的方法名统一起来
    • 抽象类只能被继承,不能实例化
    import abc
    class Animal(metaclass=abc.ABCMeta):# 通过抽象类使子类中的方法名统一起来
    	@abc.abstractmethod
    	def run(self):
    		pass
    
    	@abc.abstractmethod
    	def eat(self):
    		pass
    
    class People(Animal):
    
    	def run(self):
    		pass
    
    	def eat(self):
    		pass
    
    class Pig(Animal):
    
    	def run(self):
    		pass
    
    	def eat(self):
    		pass
    
    

    多态与多态性

    • 同一种事物的多种形态
    多态性:
    • 可以在不考虑对象的类型的情况下而直接使用对象
      • 如抽象类中只要是动物都有的属性,不管属于什么分类,都有这一个方法,可以直接使用
    • 多态性的好处:
    1. 增加类程序的灵活性
      • 以不变应万变,不论对象千变万化,都可以通过统一接口调用
    2. 增加类程序可扩展性
      • 通过继承父类创建类一个新类,使用者无需更改自己的代码,还是用同样的方法去调用
    • python崇尚的是一种鸭子类型

    封装

    如何实现属性的隐藏
    class A:
    	__x = 1 #_A__x=1
    	
    	def __init__(self,name):
    		self.__name=name
    		
    	def __foo(self):
    		print('run foo')
    
    • 特点:
    1. 在类外部无法直接使用
    2. 在类内部可以直接使用
    3. python并不真正隐藏,只是在类定义是进行了变形操作
    4. 子类无法覆盖父类__开头的属
    封装的意义
    • 封装数据属性:明确区分内外,控制外部对隐藏的属性的操作行为

    • 封装方法:隔离复杂度

    封装与扩展性
    property的使用

    propert:特性

     class People:
    	def __init__(self,name):
    		self.__name = name
    	@property
    	def name(self):
    		return self.__name
    
    	@name.setter
    	def name(self,val):
    		if not isinstance(val,str):
    			print('val is not str')
    			return
    		self.__name = val
    	@name.deleter
    	def name(self):
    		print('不允许删除')
    
    p = People('wualin')
    print(p.name)
    
    绑定方法与非绑定方法
    • 绑定方法:

      • 绑定给谁,就应该由谁来调用,谁来调用就把调用者当作第一个参数自动传入

      • 绑定到对象的方法:在类内定义的没有被任务装饰器修饰的

      • 绑定到类的方法:在类内部定义的装饰器classmethod修饰的方法

    • 非绑定方法:不会自动传值,就是类中的普通工具,类和对象都可以使用

      • 非绑定方法:不与类或者对象绑定
    class Foo:
    	def __init__(self,name):
    		self.name = name
    
    	def tell(self):# 绑定到对象的函数
    		print('name:%s'%self.name)
    
    	@classmethod
    	def func(cls): #cls=Foo	绑定到类的方法
    		print(cls)
    
    	@staticmethod
    	def func1(x,y):#类中的普通函数
    		print(x+y)
    
    f = Foo('wualin')
    Foo.func1(1,2)
    f.func1(1,3)
    
    • 绑定方法与非绑定方法的实际应用场景

    反射

    • 通过字符串映射到对象的属性
    hasattr(obj,'name')# 判断对象有没有'name'属性 obj.__dict__['name']
    
    getattr(obj,'name') # 拿到对象的属性
    
    setattr(obj,'name','wualin')#修改 obj.name = 'wualin'
    
    delattr(obj,'age')# del obj.age
    以上方法同样适用于类
    
    • 反射的应用:
    class Service:
    	def run(self):
    		while True:
    			cmd = input('>>>:').strip()
    			if hasattr(self,cmd):
    				func = getattr(self,cmd)
    				func()
    	def get(self):
    		print('get...')
    		
    	def put(self):
    		print('put...')
    obj = Service()
    obj.run()
    
    内置方法
    • isinstance(obj,cls) 检查obj是否是类cls的对象
    class Foo(object):
        psss
    obj = Foo()
    isinstance(obj,Foo)
    
    • issubclass(sub,super) 检查sub类是否是super的派生类(子类)
    class Foo():
        pass
    class Bar(Foo):
        pass
    issubclass(Bar,Foo)
    
    • item系列:
    # item
    class Foo():
    	def __init__(self,name):
    		self.name = name
    
    	def __getitem__(self, item):#查看
    
    		return self.__dict__.get(item)
    
    	def __setitem__(self, key, value):#增加
    		self.__dict__[key] = value
    
    	def __delitem__(self, key):#删除
    		del self.__dict__[key]
    
    obj = Foo('wualin')
    #操作字典的方式去操作obj对象
    #查看
    print(obj['name']) #obj.name
    
    #增加
    obj['age'] = 20 #obj.age = 20
    print(obj['age'])
    
    #删除
    del obj['name'] #del obj.name
    
    • str
    class Foo():
    	def __init__(self,name,age):
    		self.name = name
    		self.age = age
    
    	def __str__(self):
    
    		return '<name:%s age:%s>'%(self.name,self.age)
    
    f = Foo('wualin',20)
    print(f)
    
    • del:在对象被删除时先触发__del__,可自定义回收系统资源
    class Open():
    	def __init__(self,filename):
    		print('Open...')
    		
    	def __del__(self):
    		print('del...')
    f = Open('a.txt')
    print('---main---')
    
    • call
    class Foo:
        def __call___(self,*args,**kwargs)
            print(self)
            print(args)
            print(kwargs)
    obj = ()
    obj(1,2,3,a=1,b=2,c=3)#obj.__call__(obj,1,2,3,a=1,b=2,c=3)
    
    
    

    元类介绍

    • exec命令的使用:
    1. 参数1:字符串形式的命令
    2. 参数2:全局作用域(字典形式),如果不指定默认使用globals()
    3. 参数3:局部作用域(字典形式),如果不指定默认使用locals()
    • 对象可以怎么使用?
      • 都可以被引用:x = obj
      • 都可以当作函数的参数传入
      • 都可以当作函数的返回值
      • 都可以当作容器类
    • 产生类的类称之为元类,默认使用class定义的类,他们的元类是type
    • 定义类的三要素:
    1. 类名
    2. 类的基类
    3. 类的局部名称空间:obj.dict()
    • 定义类的两种方式:
      • 方式1:class

      • 方式2:type

    class_name = 'Chinese' #类名
    class_bases = (object,) #类的基类
    class_body = 
    '''
    country = 'china'
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def talk(self)
        print('%s is talking'$self.name)
    '''
    class_dic = {}# 类的局部名称空间
    exec(class_body,globals(),class_dic)
    Chinese1 = type(class_name,class_bases,clsaa_dic)
    
    自定义元类控制类的行为
    class Mymeta(type):
        '''
        给传入class_name添加首字母必须大写,否则抛出异常,如果定义类的元类是Mymeta(metaclass=),就必须遵循自定义规则
        '''
    	def __init__(self,class_name,class_bases,class_dic):
    		if not class_name.istitle():
    			raise TypeError('首字母大写') #raise主动抛出错误
    class Chinese(object,metaclass=Mymeta):
    	def __init__(self,name,age):
    		self.name = name
    		self.age = age
    
    	def tall_info(self):
    		print('Name: %s Age: %s'%(self.name,self.age))
    
    自定义元类控制类的实例化行为
    class Mymeta(type):
    	def __call__(self, *args, **kwargs):
    		'''
    		实例化类的步骤:
    		1. 生成obj对象
    		2. 初始化obj对象
    		3. 返回obj
    		:param args:
    		:param kwargs:
    		:return:
    		'''
    		obj = object.__new__(self)
    		self.__init__(obj,*args,*kwargs)
    		return obj
    
    class Chinese(object,metaclass=Mymeta):
    	def __init__(self,name,age):
    		self.name = name
    		self.age = age
    
    	def tall_info(self):
    		print('Name: %s Age: %s'%(self.name,self.age))
    obj = Chinese('WUALIN',20)
    print(obj.__dict__)
    
    自定义元类控制类的实例化行为的应用
    • 单例模式:
    class MySQL:
    	'''
    	假如一个类初始化属性都是一样的,可以使用单例模式节省内存空间
    	'''
    	__instance = None
    	def __init__(self):
    		self.host = '127.0.0.1'
    		self.port = 3306
    	
    	@classmethod
    	def singleton(cls): #单例模式函数,生成实例化对象时调用该函数
    		if not cls.__instance:
    			obj=cls()
    			cls.__instance=obj
    		return cls.__instance
    # 两次实例化对象内存地址是一样的	
    obj1 = MySQL.singleton()
    obj2 = MySQL.singleton()
    
    • 通过元类实现单例模式:
    class Mymeta(type):
    	def __init__(self,class_name,class_bases,class_dic):
    		if '__doc__' not in class_dic or not class_dic['__doc__'].strip():
    			raise TypeError('注释不能为空')
    
    		super(Mymeta,self).__init__(class_name,class_bases,class_dic)
    
    		self.__instance = None
    	def __call__(self, *args, **kwargs):
    		if not self.__instance:
    			obj = object.__new__(self)
    			self.__init__(obj)
    			self.__instance = obj
    		return self.__instance
    
    class Mysql(object,metaclass=Mymeta):
    	'''
    	xxx
    	'''
    	def __init__(self):
    		self.host = '127.0.0.1'
    		self.port = 3306
    
    obj1 = Mysql()
    obj2 = Mysql()
    print(obj1 is obj2)
    
    面向对象的软件开发
  • 相关阅读:
    Async/await 和 Promises 区别
    javaScript 如何使用js追加字符串呢?
    JavaScript深入之继承的多种方式和优缺点
    在原生JavaScript中创建不可变对象
    websocket的用途/场景
    爬虫新宠requests_html 带你甄别2019虚假大学 #华为云·寻找黑马程序员#
    #华为云·寻找黑马程序员#微服务-你真的懂 Yaml 吗?
    #华为云·寻找黑马程序员#【代码重构之路】使用Pattern的正确姿势
    Python-Excel 模块哪家强 #华为云·寻找黑马程序员#
    多元算力加持,华为云鲲鹏大数据服务公测上线
  • 原文地址:https://www.cnblogs.com/wualin/p/9777548.html
Copyright © 2011-2022 走看看