zoukankan      html  css  js  c++  java
  • 面向过程与面向对象(一)

    一.面向过程与面向对象:

      面向过程:

     重过程:解决问题,考虑的是解决问题的流程
     解决问题的思路清晰,但拓展性不强

     

      面向对象:
     重对象:解决问题,找到解决问题的对象
     解决问题的思路可能不止一条(理解解决问题的难度增加),但拓展性强

    二.名称空间:

     能产生名称空间的有:文件 | 函数 | 类
     能产生名称空间的对象有__dict__这个值,通过该这个值访问到名字与地址的对应关系

    def func():
        pass
    
    func.__dict__['index'] = 10000
    print(func.__dict__)
    属性:
    print(func.__dict__['index']) print(func.index)
    方法: func.add
    = lambda n1, n2: n1 + n2 print(func.__dict__) print(func.add(10, 20))

    三.类与对象:

    类:具有相同特征与行为个体集合的抽象
     对象:有特征、行为的具体个体,就是类的具体体现

    1.类拥有自己的名称空间,类的对象也拥有自己的名称空间

    2.属性的访问顺序:对象优先加载自身的属性与方法,如果没有再考虑类的

    四.对象的特有的名称空间:

    class Student:
        # __init__方法会在实例化对象时被调用 , student=Student()
        # 1.会为实例化的对象形成空的名称空间
        # 2.就是一个方法,可以被传参,在 类名(实参) 这种方式下调用并传参 __init__(self, 形参)
        # 3.第一个self就是要产生的当前对象
        # 重点:在方法内部,形参拿到了实参值,利用self.属性名 = 形参 = 实参值,对对象的名称空间添加属性
        def __init__(self, name, sex):
            print('2>>>', self)
            self.name = name
            self.sex = sex
    
    
        def fn():
            print('fn run')

    五.对象绑定类方法:

    class A:
        def test(self):
            print(self)
            pass
    a = A()
    #绑定的三种方式: a.test() A.test(a) A.
    __dict__['test'](a)

    六.类方法的调用:

    class Tool:
        # 类方法:可以被类与对象调用的方法,第一个参数一定是类
        # 类方法不建议拿对象来调用
        @classmethod
        def add(cls, n1, n2):
            print(id(cls))
            cls.test()
            return n1 + n2
    
        @classmethod
        def test(cls):
            pass
    
    print(Tool.add(10, 20))
    tool = Tool()
    print(tool.add(100, 200))
    print(id(Tool), id(tool))
    
    # 对象调用所属类的类方法,默认第一个参数传入的是 对象.__class__ 就是所属类

    七.属性与方法的总结:

    class OldBoy:
        # 属于类的属性
        name = '老男孩'
    
        # 属于对象的属性
        def __init__(self, name):
            self.name = name
    
        # 属于类的方法
        # 需求:获取机构的名字
        @classmethod
        def get_class_name(cls):
            return cls.name
    
        # 属于对象的方法
        # 需求:获取校区的名字
        def get_school_name(self):
            return self.name
    
    # 先创建校区
    shanghai = OldBoy('上海校区')
    shenzhen = OldBoy('深圳校区')
    
    # 类方法的使用
    # 建议使用类调用
    print(OldBoy.get_class_name())
    # 类方法拿对象调用并没有多少新增的意义,不建议拿对象调用
    print(shanghai.get_class_name())
    print(shenzhen.get_class_name())
    
    # 对象方法的使用
    # 类调用对象方法,必须把要操作的对象手动传入,不建议使用
    print(OldBoy.get_school_name(shanghai))
    print(OldBoy.get_school_name(shenzhen))
    # 对象调用对象方法,默认将自身传入,建议使用
    print(shanghai.get_school_name())
    print(shenzhen.get_school_name())
    

    八.封装:

          简单地说, 将方法与属性打包封在一个类中称为封装,方便之后调用操作.

    九.类的隐藏:

         隐藏:对外隐藏类中一些属性与方法的实现细节
         优点:外界不能直接访问,让内部的属性与方法具有安全保障

    class A:
        # __开头的属性,在外界不能通过 cord | __cord 直接访问:对外隐藏了
        __cord = '01012300'
    
        # __开头的方法,在外界不能通过 get_money | __get_money 直接访问:对外隐藏了
        @classmethod
        def __get_money(cls):
            print('输入密码,取出100w零花钱')
    
        # 内部还是可以直接访问__开头的属性与方法
        @classmethod
        def test(cls, flag):
            print('test方法被外界调用')
            # 在调用test与访问具体数据与功能间添加安全处理的操作
            if flag == '自家人':
                print(cls.__cord)
                cls.__get_money()
    

      隐藏原理: 把用__开头的名字更名为 _类名__变量名

    # print(A.__dict__)
    print(A._A__cord)
    A._A__get_money()

    十.对象的隐藏(利用接口调用):

    class AAA:
        def __init__(self, money):
            self.__money = money
    
        # 取值
        @property  # 在外界可以 对象.money 进行取值
        def money(self):
            # print('走方法拿到的money')
            return self.__money
    
        # 赋值
        @money.setter  # 在外界可以 对象.money = 新值 进行赋值
        def money(self, money):
            self.__money = money
    
        # 删除
        @money.deleter
        def money(self):
            # print('逗你玩')
            del self.__money
    
        def get_money(self, flag):
            if flag == '自家人':
                return self.__money
            return 0
    
        def set_money(self, money):
            self.__money += money
    
     
    
    print(a.money)
    a.money = 999999
    print(a.money)
    
    del a.money
    print(a.money)

    十一.组合:  自定义类的对象作为另外一个类的属性

      

    class Teacher:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    
    t1 = Teacher("Owen", 17)
    print(type(t1.name), type(t1.age))
    
    
    class Student:
        # 学生可以有 老师 属性
        def __init__(self, name, age, teacher):
            self.name = name
            self.age = age
            # 自定义类的对象作为类的属性:组合
            self.teacher = teacher
    # 创建一个学生
    stu = Student('Bob', 18, t1)
    print(stu.__dict__)
    
    # 学生的老师年龄和姓名
    print(stu.name)
    print(stu.teacher)
    print(stu.teacher.name)
    print(stu.teacher.age)

    十二.继承

        1.继承语法:

    继承的语法:
    # class 类名(父类名): pass
    
    class A:
        pass
    
    print(A.__bases__)  # object 
    没有定义的类都是继承object
    
    print(Leader.__bases__)  # Student
    定义了父类就继承父类

       2.父类隐藏后的继承:

    class Sup:
        __num = 10
    
        def __init__(self, name):
            self.__name = name
    
        @property
        def name(self):
            print(self)            # <__main__.Sub object at 0x02BA8490>
    print(self.__dic__) # 名称空间的key是'_Sup_name'
    return self.__name @classmethod def __c_fn(cls): print(cls, 'c fn') def __o_fn(self): print(self.name, 'o fn') class Sub(Sup): def test(self): print(self.__dict__) # {'_Sup__name': 'sssssssss'} print(self._Sup__name) pass sub = Sub('sssssssss') print(sub.name) sub.test()
    sub._Sup__c_fn()

      3.方法的重写(完全不用父类的):

     有继承关系下的属性查找顺序:
     1.优先找自身,自身没有找父类
     2.父类没有找父类的父类
     3.一直找到最顶级的父类,如果还没有报错
    
    # 两个名词:
    先写子类,抽离 出父类
    先写父类,派生 出子类
    class Sup:
        num = 10
    
        def test(self):
            print('test sup')
    
    class Sub(Sup):
        num = 100
    
        # 先写好父类的方法,由于父类方法的功能不满足子类需求,
        # 子类可以重写父类方法:方法名与父类相同,自定义方法的实现体
        def test(self):
            print('test sub')
    
    print(Sub.num)
    Sub().test()

      4.方法的重用(部分仍用父类的):

    class Sup:
        def test(self):
            print('>>>sup', self)
            print('test sup')
    
    
    class Sub(Sup):
        pass
        # 重用:还需要父类方法的功能,在父类方法功能基础上再添加新功能
        # 突破点:在子类中去调用父类的方法,还有保证调用者是子类(子类的对象)
        def test(self):
            # Sup().test()
    
            # python2中写法
            # super(Sub, self).test()
            # python3中简化写法
            super().test()
    
            print('>>>sub', self)
            print('test sub')
    
    
    Sub().test()

     5.__init__结合super()使用:

    # 人类:只需要初始化 - name
    # 老师: 要初始化 - name salary
    # 学生: 要初始化 - name grade
    class Sup:
        def test(self):
            print(self)
    
        def __init__(self, name):
            self.name = name
    
    class Sub(Sup):
        # 有继承关系下,只要名字相同,即使产生不同,还是属于同一个方法
        def test(self, num):
            super().test()
            print(num)
    
        # 默认父级的__init__可以被继承过来,
        # 但是会出现子类对象的属性比父类多
    
        def __init__(self, name, salary):
            super().__init__(name)  # 父级有的共性功能通过super()交给父级做
            self.salary = salary  # 子类特有的自己来完成
    
    # Sub().test(10)
    # Sub().test()  # 使用还是使用自身带参的,不能使用父级不带参的
    # (本质名字相同就是一个,优先查找自己的)

         6.多继承:

    # 简单的多继承
    '''
    # 属性的查找顺序:优先找自己的,如果没有,按照继承先后查找父级
    class A:
        name = 'A'
        num = 10
    
    class B:
        name = 'B'
        count = 100
    
    # 子类可以继承所有父类的所有可继承属性
    class C(A, B):  # 自己 => A => B
        # name = 'C'
        pass
    
    print(C.num)
    print(C.count)
    print(C.name)
    # 打印属性查找的顺序
    print(C.mro())
    '''
    
    # 复杂的多继承
    '''
    class A:
        name = "A"
    class B(A):
        name = "B"
    class C:
        name = "C"
    class D(C):
        name = "D"
    class E(B, D):
        name = "E"
    print(E.mro())
    '''
    
    # 经典类:python2中才有,没有继承任何类的类
    # 新式类:python2中直接或间接继承object的类,python中所定义的所有类
    
    
    class G: name = "G"
    class C(G): pass
    class B(C): pass
    class E(G): pass
    class D(E): name = "D"
    class F(G): pass
    class A(B, D, F): pass
    print(A.mro())

        7.菱形继承:

     经典类:python2中才有,没有继承任何类的类 - 深度优先 新式类:python2中直接或间接继承object的类,python中所定义的所有类 - 广度优先
    
     深度优先,在查找第一个分支是就将菱形的头查找了 广度优先,菱形的头在所有分支查找接收后再被查找
    
     通过 类.mro() 查看继承顺序图

    十三.接口思想:

    # 接口类:用来定义功能的类,为继承它的子类提供功能的,
    # 该类的功能方法一般不需要有实现体,实现体有继承它的子类自己去实现
    class PetInterface:
        def close_master(self): pass
    
    class WatchInterface:
        def watch_door(self): pass
    
    class Dog(PetInterface, WatchInterface):
        def jiao(self): pass
    
        def chi(self): pass
    
        def pao(self): pass
    
        # 一定要重写接口的方法

    十四.抽象类:

    # 抽象父类:拥有抽象方法(子类共有的方法,但是父类不能有具体的实现体)的父类
    #       抽象方法:方法名是具体的,但是实现体是抽象的(在子类中重写来具象化)
    
    # python中借助abc来实现抽象父类
    import abc  # abstract base class
    class Quan(metaclass=abc.ABCMeta):
        def __init__(self, name):
            self.name = name
        def run(self):
            print(self.name + 'running')
    
        # 抽象父类中的抽象方法,在继承它的子类中必须有自己的实现体
        #       -- 抽象父类中的抽象方法实现体就没有意义,实现与不实现都是pass填充
        @abc.abstractmethod
        def chi(self):
            # print(self.name + '肉')
            pass
        @abc.abstractmethod
        def jiao(self):
            # print('汪汪汪')
            pass
    
        @classmethod
        @abc.abstractmethod
        def fn(cls): pass
    
    class Dog(Quan):
        @classmethod
        def fn(cls): pass
    
        def kanmen(self):
            print(self.name + '看门')
        def chi(self):
            super().chi()
            print(self.name + '狗粮')
        def jiao(self):
            print('汪汪汪')
    
    class Wolf(Quan):
        @classmethod
        def fn(cls): pass
    
        def bulie(self):
            print(self.name + '捕猎')
        def chi(self):
            print(self.name + '')
        def jiao(self):
            print('嗷嗷嗷')
    
    dog = Dog('来福')
    wolf = Wolf('常委')
    
    dog.jiao()
    # wolf.jiao()
    # dog.run()
    # wolf.run()

    十五.多态:

    # 多态:对象的多种状态 - 父类对象的多种(子类对象)状态
    
    import abc
    class People(metaclass=abc.ABCMeta):
        def __init__(self, name):
            self.name = name
    
        @abc.abstractmethod
        def speak(self): pass
    
    class Chinese(People):
        def speak(self):
            print('说中国话')
    
    class England(People):
        def speak(self):
            print('说英国话')
    
    
    if __name__ == '__main__':
        # 多态的体现:功能或是需求,需要父类的对象,可以传入父类对象或任意子类对象均可以
        #       注:一般都是规定需要父类对象,传入子类对象
        def ask_someone(obj):
            print('让%s上台演讲' % obj.name)  # 父类提供,自己直接继承
            obj.speak()  # 父类提供,只不过子类重写了
    
        ch = Chinese('王大锤')
        en = England('Tom')
    
        ask_someone(ch)
        ask_someone(en)

    十六.鸭子类型

    import abc
    class People(metaclass=abc.ABCMeta):
        def __init__(self, name):
            self.name = name
    
        @abc.abstractmethod
        def speak(self): pass
    
    class Chinese(People):
        def speak(self):
            print('说中国话')
    
    class England(People):
        def speak(self):
            print('说英国话')
    
    # 鸭子类型:
    # 1.规定有什么属性及什么方法的类的类型叫鸭子类型
    # 2.能提供出规定的属性与方法的对象就是鸭子
    class Test:
        def __init__(self, name):
            self.name = name
        def speak(self):
            print('说鸟语')
    
    if __name__ == '__main__':
        def ask_someone(obj):
            print('让%s上台演讲' % obj.name)
            obj.speak()
    
        test = Test('鸭子')
        ask_someone(test)

    十七.格式化与析构方法

    class A:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        # 格式化方法:在外界打印该类对象是被调用
        # 格式化外界直接打印该类对象的字符串表示结果
        def __str__(self):
            # return 'abc'
            # return super().__str__()
            return '<name:%s | age:%s>' % (self.name, self.age)
    
        # 析构方法:在对象被消耗的那一刹那被调用,在被消耗前可以做一些事情
        def __del__(self):
            # del会在self代表的对象被消耗的时候被调用
            # 我们可以在析构函数中释放该对象持有的其他资源,
            # 或者将一些持有资源持久化(保存到文件或数据库中)
            del self.name  # 也可以将name存起来

    十八.反射:通过字符串与类及类的对象的属性(方法)建立关联

    class A:
        num = 10
    print(hasattr( A ,'num'))           #判断类中是否有num属性      True
    print(getattr(A,'num','default'))   #获取类中num的属性值,没有则拿默认值   10
    delattr(A,'num')                    #删除类中num属性
    setattr(A,'tag',10)                 #在类中设置一个tag属性
    
    
    class B:
        def __init__(self,name):
            self.name=name
    b = B('BOb')
    print(hasattr( b ,'name'))         #判断对象中是否有name属性      True
    print(getattr(b,'name','default')) #获取对象中name的属性值,没有则拿默认值   10
    delattr(b,'name')                  #删除对象中name属性
    setattr(b,'tag',10)                #在对象中设置一个tag属性
    print(b.tag)
    
    
    
    class C:
        def fn(self):
            print('fn')
        @classmethod
        def func(cls):
            print('func')
    
    #类调对象方法,需要传入对象当做参数
    fn=getattr(C,'fn')
    c = C()
    fn(c)
    #对象调对象方法
    c = C()
    fn=getattr(c,'fn')
    fn()
    #类调类方法
    func = getattr(C,'func')
    func()

    十九.异常处理:

    # 程序运行时的错误
    # 程序中的异常处理机制:
    # 1.程序中的所有异常都会被处理
    # 2.程序中的所有异常都需要手动处理
    # 3.如果没有手动处理异常,异常会交给Python解释器处理
    #       -- 处理的方式就是打印异常信息,并停止接收器
    
    # 异常信息的三部分:
    # 1.异常的追踪信息:提示错误位置
    # 2.异常的类型:告知处理异常应该捕获什么类型
    # 3.异常的内容:告知错误信息
    
    # 处理异常的语法:
    '''
    try:
        # 会出现异常的代码块
    except  异常类型 as 异常别名:
        # 异常处理逻辑
    else:
        # 没有出现异常会执行该分支
    finally:
        # 无论是否出现异常都会执行该分支
    '''
    
    try:
        print(adsdasadsdasadsdas)
    except NameError as e:
        print('异常信息:', e)
    else:
        print('被检测的代码块正常')
    finally:
        print('异常是否出现都会执行该分支')
    
    print('end')
  • 相关阅读:
    hdu 2874 Connections between cities(树上倍增)
    HDU 2586 How far away ?
    0-2岁宝宝早教全攻略
    0-2岁宝宝学习能力三步走
    0-6岁教育
    dedecms如何在文章列表前加上序列号
    争吵1
    当爸爸的感觉
    您未被授权查看该页HTTP错误401.1未经授权解决
    TPLink路由器登陆密码怎么破解
  • 原文地址:https://www.cnblogs.com/sima-3/p/11044539.html
Copyright © 2011-2022 走看看