面向对象全部内容

发布时间 2023-03-22 21:16:41作者: 哈哈哈哼

面向过程

        '''# python中的两大范式:1.面向过程 2.面向对象
    '''他们两个都不是新的技术,而是一种做事的思维方式'''

    面向过程核心是过程二字,即先干什么,在干什么,最后干什么,也就是机械式的思维方式

    # 生活中得例子:	
        把大象放冰箱分几步?
            1. 打开冰箱门
            2. 把大象放进冰箱
            3. 关上冰箱门
    优点:把复杂的问题简单化,进而流程化
    缺点:扩展性差
    使用场景:对扩展性要求不高的地方

    eg:
        # 注册功能'''

面向对象

 '''面向对象核心是对象二字
        # 在python中,一切皆对象
        1. 在程序中:	
            对象就是盛放'数据属性'和'功能'的容器
        2. 在生活中:
             对象就是'特征'与'技能'的结合体
     举个实际案例:
        # 以学生选课系统为例'''

类的定义和对象的产生

# 在程序中,必须先定义类,在调用类产生对象
    class Student():
        pass
    
    """
    	定义类发生的事情?
    		1. 会立即执行类体代码
    		2. 产生类的名称空间,把类中得名字丢到类的名称空间去
    		3. 把类的名称空间绑定给__dict__,类名.__dict__
    """
    # 产生对象
    调用类:类名()
    得到一个对象,这个对象默认是空对象
    obj = Student()
    '''得到的对象也有他自己的名称空间'''
    obj.__dict__  # {}

定制对象自己独有的属性

class Student():
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.gender=gender
     obj=Student('kevin', 20, 'female') # obj=Student('kevin', 20, 'female')
    print(obj.name,obj.age,obj.gender)
    print(obj.__dict__) # {'name':'kevin', 'age':20, 'gender':'female'}

属性的查找顺序

1. 类属性
    	# 直接在类中查找,找不到直接报错
        #类属性的查找
        print(student.school)
        #类属性的增加
        student.name="xxx"
        #类属性的删除
        del student.name
    2. 对象属性
    	# 先从自己的名称空间中找,在从产生这个对象的类中找,在找不到,就报错
        #对象属性的查看
        stu.name
        stu.__dict__["name"]
        #对象属性的修改
        stu.name="xxx"
        #对象属性的删除
        del stu.name

绑定方法和非绑定方法

# 绑定方法:绑定给类的方法和绑定给对象的方法
    1. 绑定给对象的方法:
    	# 对象来调用,特殊之处:会把对象自己当成第一个参数传给方法的第一个形参self
        # 类来调用绑定给对象的方法:类名来调用,方法里面有几个参数就传几个参数,包括self
    2. 绑定给类的方法
    	'''前提:要在方法的头上加一个装饰器:@classmethod'''
    	# 类来调用,特殊之处:会把类名当成第一个参数传给方法的第一个形参cls
非绑定方法:
	'''前提:在方法的头上加一个装饰器:@staticmethod'''
	# 既不绑定给类也不绑定给对象
    类和对象都可以来调用,并且都不用传递参数

隐藏属性

# 如何隐藏?在名字的前面加上__名字
    '''
    	1. 在类的定义阶段隐藏的,名字发生了变形:_类名__名字
    	2. 在类的外部原则上不能用了,非要使用也可以使用
    	3. 隐藏属性对外不对内
    '''
    # 为什么要隐藏?
    	在类的内部开放一个接口来返回类中隐藏的属性,可以更好的对属性做限制

property装饰器

# 把方法伪装成属性
    '''把方法伪装成属性之后,以后再调用方法的时候,就不用加括号了,只需要点属性名即可'''
    1. @property
    2. @方法名字.setter
    3. @方法名字.deleter
    # 另外一种用法
    在类的内部使用property()函数
    class Foo:
    	xxx = property('get_country', 'set_country', 'del_country')
    obj = Foo()
    obj.xxx
    obj.xxx = 'a'
    del obj.xxx 

继承

"""
		1. 继承就是新建类的一种方式,被创建出来的类是子类或者叫派生类,被继承的类称为父类或者基类
		2. 继承解决类与类之间的代码冗余问题
		3. 在子类括号里面写上继承的父类名字
		4. 子类可以遗传父类的所有属性和方法
		5. python中,支持单继承和多继承
	"""
    class Foo():
        pass
    
    class Bar(Foo):
        pass
    '''# 单继承子类只能继承一个父类,括号里面只有一个类
    '''
        1.先从对象自己的名称空间中取查找
        2.在从产生这个对象的类中查找
        3.去继承的父类中继续依次往上查找
        4.在查找的过程中,如果查找到一个,就不在继续往下找了
    '''
    '''
    # 多继承就是括号里面可以有多个父类,继承的父类中也可以有多个父类
    '''菱形查找和非菱形查找'''
    1. 经典类
        # 按照深度优先的查找顺序,继承的类中从左往右依次查找,从第一个分支一直找到顶点

    2. 新式类
        # 按照广度优先查找,继承的类中从左往右依次查找,从最后一个分支找到顶点
    '''实际工作中,能用单继承实现的就尽量不要使用多继承'''
   '''单继承下的属性查找:先在增加的名称空间查找,再从产生这个对象的类中去查找
   ,然后再去类所继承的基类中查找'''
   '''多继承下的属性查找:菱形查找一定是被继承的多个类最终汇聚到应该点上'''
	"""
		1. 多继承分菱形继承和非菱形继承
		2. 经典类和新式类的查找
			在Python2中会出现经典类
		3. 经典类的属性查找顺序:深度优先
		4. 新式类的属性差债:广度优先
	"""

super和mro

# python2:super(Student,self).__init__()
    # python3:super().__init__()
    '''遇到多继承中出现了super关键字,如何更准确的知道它的查找顺序,我们需要打印出类的mro列表'''
    print(类名.mro())

多态

# 抽象类
    '''
    	抽象类的特点:只能被继承,不能被实例化
    '''
    '''抽象类中得父类属性和方法不是让子类来异常的,抽象类中父类可以强制限制子类的行为'''
    import abc
    class People(metaclass=abc.ABCMeta):#抽象类
        @abc.abstractmethod
        def speak(self):
            pass
        
    class People():
        def speak(self):
            raise Exception('必须实现该方法')#通过产生异常来规范派生类
            
    class Student(People):
        def speak(self):
            pass
        
 	# python崇尚的鸭子类型
    '''多态带来的特性:在不考虑对象的类型下,直接调用对象的对应方法'''
     
    def len(obj):
        return obj.__len__()
    len('abcd')
    len([1,2,3,4])
    len({'a':1})

    '''
        鸭子类型:它是一种动态的编程风格,我们更多关注的是对象的行为,而不是对象的类型,我们不用在使用type或者isinstance查出它的类型了

        允许我们在调用方法的时候,只要对象拥有这个方法,我们就可以当成参数传递过去,而无需关心类型!!!!
    '''

组合

#一个对象拥有一个属性,该属性的值是一个对象
    '''使用场景,满足什么有什么的时候'''

内置方法(魔术方法简称魔法)

    ```python
    1. __init__ ## 初始化方法,调用类的时候自动触发,里面有一个self参数,用来接收对象的
    2. __str__,__repr__
        """
            1. 打印对象或者输出对象的时候,会自动触发
            2. 返回值必须是字符串,不能没有返回值
            3. 如果同时存在的时候,__str__的优先级最高
            4. 一般情况都用了__str__,偶尔也会遇到__repr__
        """
    3. __del__
        """
            1. 删除对象的时候触发
            2. 当程序全部执行完毕的时候也会触发
            3. 一般用在回收系统资源的时候使用
        """
    4. __doc__
        # 查看类的信息 ===》注释
    5. __enter__,__exit__
        '''
            1. 当出现with语句的时候,会触发__enter__
            2. __enter__方法执行之后,开始执行with语法的代码块
            3. 当with语句执行完毕之后,执行__exit__方法
            4. 当with代码块中出现了异常,在__exit__方法中能够得到异常的信息,(异常类型,异常值,追溯信息)
            5. 如果在__exit__方法中:return True,可以清除异常,相当于什么都没发生
        '''
    6. __getattr__,__setattr__,__delattr__
        '''
            1. __getattr__:当使用句点符查找不存在的属性的时候触发
            2. __setattr__: 当使用句点符修改存在的属性值或者增加不存在的属性值得时候会自动触发
            3. __delattr__: 删除一个属性的时候,会自动触发
        '''
    7. __getitem__,__setitem__,__delitem__
        """
            1. __getitem__:当通过中括号取值的时候,会自动触发
            2. __setitem__: 当通过中括号改值的时候,会自动触发
            3. __delitem__: 当通过中括号删除值得时候,会自动触发
        """
    8. __call__
        """
            当给对象加括号调用的时候会自动触发!!!
        """
    ```

反射

```python
    # 通过字符串来操作对象的属性
    1. getattr(stu, 'name',666)
        """
            1. 如果第二个参数是属性的话,直接返回属性的值
            2. 如果属性不存在,会报错
            3. 如果写了第三个参数,当属性不存在的时候,会把第三个值返回
            4. 如果第二个参数是函数名(方法名)的话,返回的是函数的内存地址,如果想调用,直接返回的结果加括号
        """
    2. setattr(stu, 'x', '666') #当属性不存在,增加属性,当属性存在,修改值

    3. delattr(stu, 'x')
    4. hasattr(stu, 'x')#返回True或者False
    补充:
        1. 以上4个方法中得第一个参数也可以写模块名
            import time
            time.sleep(3)

            sleep=getattr(time, 'sleep')
            sleep(3)
        2. __import__
        # 通过字符串的形式导入模块
        time=__import__('time')
        time.sleep()
        反射案例
          class FtpServer:
            def serve_forever(self):
                while True:
                    inp = input('input your cmd>>: ').strip() # get a.txt
                    cmd, file = inp.split() # get a.txt
                    if hasattr(self, cmd):  # 根据用户输入的cmd,判断对象self有无对应的方法属性
                        func = getattr(self, cmd)  # 根据字符串cmd,获取对象self对应的方法属性
                        func(file)


            def get(self, file):
                print('Downloading %s...' % file)

            def put(self, file):
                print('Uploading %s...' % file)

        server = FtpServer()
        server.serve_forever()

    ```

异常

```python
    1. 主动抛出异常
        # 关键字是:raise
        raise Exception('')
        raise TypeError('')
        raise IndexError('')
        raise KeyError('')
    '''父类限制子类的行为:'''
    class Animal():
        def speak(self):
            raise Exception('必须实现speak方法')
    class People(Animal):
        def speak(self):
            pass

    obj = People()
    obj.speak()
    2. 自定义异常
        # 1. 先写一个自定义类,
        # 2. 继承BaseException
        # 3. raise 抛出异常
    3. 断言
        assert 表达式
        '''表达式的条件一定是True,否则直接报错'''
        ...
        d = {'token':'dasdasdasdasdasdasdsad'}
        assert 'token' in d
    ```

日志

# 记录代码在执行过程产生的一些变化,我们需要记录下来,记录的内容有可能是正确的,也有可能是错误的
    大多数用在记录代码在运行的过程中产生的异常
    # 实际工作中得日志一般放在数据库中,还有工作有专门的日志系统,es搭建的日志
    Elasticsearch:搜索引擎

    # 日志级别:5个级别
        debug   	=>  10
        info    	=>  20
        warning  	=>  30
        error     	=>  40
        critaca		=>  50
    # 使用logging模块
    import logging
    logging.debug('日志信息')
    logging.info('日志信息')
    logging.warning('日志信息')
    logging.error('日志信息')
    logging.critaca('日志信息')