zoukankan      html  css  js  c++  java
  • 面向对象

    面向对象

    面向对象编程:是一类相似功能函数的集合,使你的代码更清晰化,更合理化

    1.面向对象的结构(第一部分:静态属性 属性 静态变量 静态字段)/(第二部分:方法 函数 动态属性)

    class Stu:
        study = "学习"#静态属性
        exam = "考试"#静态属性
    
        def work(self):#动态属性
            print("每天上课")
        def homework(self):
            print("写作业")
    class是类的关键字,即为定义一个类
    Stu为类名  使用大驼峰命名风格 首字母大写
    

    2.类名操作静态属性

    1查看类中的内容:.__dict__ 类名.__dict__
    class Stu:
        study = "学习"#静态属性
        exam = "考试"#静态属性
    
        def work(self):#动态属性
            print("每天上课")
        def homework(self):
            print("写作业")
    print(Stu.__dict__)
    #{'__module__': '__main__', 'study': '学习', 'exam': '考试', 'work': <function Stu.work at 0x000001280185CBF8>, 'homework': <function Stu.homework at 0x000001280185CC80>, '__dict__': <attribute '__dict__' of 'Stu' objects>, '__weakref__': <attribute '__weakref__' of 'Stu' objects>, '__doc__': None}
    
    2.万能的点.
    class Stu:
        study = "学习"#静态属性
        exam = "考试"#静态属性
    
        def work(self):#动态属性
            print("每天上课")
        def homework(self):
            print("写作业")
    print(Stu.__dict__)
    查
    print(Stu.study)
    print(Stu.exam)
    
    增
    Stu.close = "校服"
    print(Stu.close)
    
    删
    del Stu.close
    print(Stu.__dict__)
    
    改
    Stu.exam = "不想考试"
    print(Stu.exam)
    

    3.类名操作动态方法

    class Hun:
        mind = "有点思想"
        dic = {}
        l1 = []
        def work(self):
            print("人类会工作")
        def too(self):
            print("人类会使用工具")
    hun.work(11)#11为参数,work中的self需要接受一个参数
    

    4.从对象的角度研究类

    类名+()就是一个实例化过程 就会实例化成一个对象
    class Human:
        mind="有思想"
        language = "使用语言"
        def __init__(self,name,sex,age,hobby):
       #self就是类中方法的第一个位置参数,self 和obj指向的同一内存地址 name,sex,age,hobby就是self封装的四个属性
            self.姓名=name
            self.性别 = sex
            self.年龄 = age
            self.爱好 = hobby
            print(self)#<__main__.human object at 0x00000258965EDC18>
            #self 和obj指向的同一内存地址
    
    obj = Human("barry","男",18,"运动")
    obj.职业 = "it"#增
    obj.性别 = "女"#改
    del obj.性别   #删
    print(obj.年龄)#查
    print(obj.__dict__)
    print(obj)#<__main__.Human object at 0x00000258965EDC18>
    1.在内存中开辟了一个对象空间
    2.自动执行类中的__init__方法,并将这个对象空间(内存地址)传给了__init__方法的第一个位置参数self。
    3.在__init__ 方法中通过self给对象空间添加属性
    
    一个类实例化多个对象
    class Human:
        mind="有思想"
        language = "使用语言"
        def __init__(self,name,sex,age,hobby):
            self.姓名=name
            self.性别 = sex
            self.年龄 = age
            self.爱好 = hobby
    obj1 = Human('小胖','男',20,'美女')
    obj2 = Human('相爷','男',22,'肥女')
    print(obj1.__dict__)
    print(obj2.__dict__)
    #{'姓名': '小胖', '性别': '男', '年龄': 20, '爱好': '美女'}
     {'姓名': '相爷', '性别': '男', '年龄': 22, '爱好': '肥女'}
    

    继承

    继承的有点也是显而易见的:
    1,增加了类的耦合性(耦合性不宜多,宜精)。
    2,减少了重复代码。
    3,使得代码更加规范化,合理化
    
    # 单继承
    class People:
        mind = "有思想的"
        def __init__(self,name,age):
            self.name = name
            self.age = age
    class Animal(People):
        mind = "无脑的"
    
    People为父类,基类,超类,Animal为子类,派生类
    obj = People("八戒",36)
    obj1 = Animal("八戒",36)
    实例化对象时必须执行__init__方法,类中没有,从父类找,父类没有,从object类中找。
    先要执行自己类中的方法,自己类没有才能执行父类中的方法
    print(obj.mind)
    print(obj1.mind)
    
    
    # 同时执行类和父类的方法
    # 方法一
    class Ainmal:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    class People:
        def __init__(self,name,age,sex,hobby): #父类方法重构 增加hobby是为了区别人类和动物的区别,但还要用之前人和动物的共同属性,在原来的基础上增加hobby
            Ainmal.__init__(self,name,age,sex) #调用Ainmal中的__init__
            self.hobby = hobby                 #添加hobby
    obj = Ainmal("八戒",36,"男")
    obj1 = People("八戒",36,"男","女")
    print(obj.__dict__)
    {'name': '八戒', 'age': 36, 'sex': '男'}
    print(obj1.__dict__)
    {'name': '八戒', 'age': 36, 'sex': '男', 'hobby': '女'}
    
    
    # 方法二
    class Ainmal:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    class People(Ainmal):
        def __init__(self,name,age,sex,hobby):
            super(People,self).__init__(name,age,sex) # 完整版
            super().__init__(name,age,sex)            # 简写版
            self.hobby = hobby
    
    obj = People("八戒",36,"男","女")
    print(obj.__dict__)
    {'name': '八戒', 'age': 36, 'sex': '男', 'hobby': '女'}
    
    
    class Ainmal:
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def eat(self):
            print("吃饭")
    class People(Ainmal):
        def __init__(self, name, age, sex, hobby):
            super(People, self).__init__(name, age, sex)  # 完整版
            super().__init__(name, age, sex)  # 简写版
            self.hobby = hobby
    
        def eat(self):
            super().eat()   #调用父类中的方法
            print(f"{self.name}吃饭")
    obj = People("八戒", 36, "男", "女")
    print(obj.__dict__)
    obj.eat()
    # 吃饭
    # 八戒吃饭
    
    
    # 单继承练习
    # 第一题
    class Base:
        def __init__(self, num):
            self.num = num
        def func1(self):
            print(self.num)
    
    class Foo(Base):
        pass
    obj = Foo(123)
    obj.func1()
    """
    先在本类中找 Foo为本类
    1.obj = Foo(123)实例化对象,自动执行__init__方法,此时self = obj,num = 123
    2.执行obj.func1(),首先在Foo的类中找func1,Foo中没有,到父类中找func1,执行func1 ,打印123
    """
    
    # 第二题
    class Base:
        def __init__(self, num):
            self.num = num
        def func1(self):
            print(self.num)
    class Foo(Base):
        def func1(self):
            print("Foo. func1", self.num)
    obj = Foo(123)
    obj.func1()
    """
    先在本类中找 Foo为本类
    1.obj = Foo(123)实例化对象,自动执行__init__方法,此时self = obj,num = 123
    2.执行obj.func1(),首先在Foo的类中找func1,Foo有,则执行func1 ,打印   Foo. func1 123
    """
    
    # 第三题
    class Base:
        def __init__(self, num):
            self.num = num
        def func1(self):
            print(self.num)
            self.func2()
        def func2(self):
            print("Base.func2")
    class Foo(Base):
        def func2(self):
            print("Foo.func2")
    obj = Foo(123)
    obj.func1()
    """
    先在本类中找 Foo为本类
    1.obj = Foo(123)实例化对象,自动执行__init__方法,此时self = obj,num = 123
    2.执行obj.func1(),首先在Foo的类中找func1,Foo中没有,去父类中找func1,父类中有,则执行func1 ,打印123
    3.继续执行func2 也是先去Foo中找func2 找到则执行,找不到则在父类中继续找 结果 123  Foo.func2
    """
    
    # 第四题
    class Base:
        def __init__(self, num):
            self.num = num
        def func1(self):
            print(self.num)
            self.func2()
        def func2(self):
            print(111, self.num)
    class Foo(Base):
        def func2(self):
            print(222, self.num)
    lst = [Base(1), Base(2), Foo(3)]
    for obj in lst:
        obj.func2()
    """
    1.Base(1), Base(2), Foo(3)实例化,num分别为1,2,3
    2.循环列表 1.Base(1)在执行Base(1)中的func2中内容 打印111 1  2.Base(2)中的func2中内容 打印111 2  3.执行Foo(3)在Foo中内容 222 3
    """
    
    多继承
    
    在python2x版本中存在两种类.:
      ⼀个叫经典类. 在python2.2之前. ⼀直使⽤的是经典类. 经典类在基类的根如果什么都不写.
      ⼀个叫新式类. 在python2.2之后出现了新式类. 新式类的特点是基类的根是object类。
    python3x版本中只有一种类:
    python3中使⽤的都是新式类. 如果基类谁都不继承. 那这个类会默认继承 object
    
    class A:
        pass
    class B(A):
        pass
    class C(A):
        pass
    class D(B, C):
        pass
    class E:
        pass
    class F(D, E):
        pass
    class G(F, D):
        pass
    class H:
        pass
    class Foo(H, G):
        pass
    MRO: Foo-> H -> G -> F -> E -> D -> B -> A -> C(看图)
        
    print(Foo.mro())******(直接计算)
    
    原则:从头开始. 从左往右. ⼀条路跑到头, 然后回头. 继续⼀条路跑到头. 就是经典类的MRO算法. 
    

    1565095855639

    封装 和 多态

    封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。

    所以,在使用面向对象的封装特性时,需要:

    • 将内容封装到某处
    • 从某处调用被封装的内容封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
    封装
    class foo:
        def __init__(self,name,age):
            self.name = name
            self.age = age
    obj1 = foo("wupeiqi",18)
    obj2 = foo("alex",73)
    通过对象直接调用被封装里的内容
    print(obj1.name)
    print(obj1.age)
    print(obj2.name)
    print(obj2.age)
    
    class foo:
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def info(self):
            print(self.name)
            print(self.age)
    间接通过self调用
    obj1 = foo("wupeiqi",18)
    obj2 = foo("alex",73)
    obj1.info()
    obj2.info()
    
    
    多态
    
    多态,同一个对象,多种形态。python默认支持多态。
    ython中有一句谚语说的好,你看起来像鸭子,那么你就是鸭子。
    对于代码上的解释其实很简答:
    class A:
        def f1(self):
            print('in A f1')
        
        def f2(self):
            print('in A f2')
    
    class B:
        def f1(self):
            print('in A f1')
        
        def f2(self):
            print('in A f2')
           
    obj = A()
    obj.f1()
    obj.f2()
    
    obj2 = B()
    obj2.f1()
    obj2.f2()
    # A 和 B两个类完全没有耦合性,但是在某种意义上他们却统一了一个标准。
    # 对相同的功能设定了相同的名字,这样方便开发,这两个方法就可以互成为鸭子类型。
    
    # 这样的例子比比皆是:str  tuple list 都有 index方法,这就是统一了规范。
    # str bytes 等等 这就是互称为鸭子类型。
    

    类的约束

    提取⽗类. 然后在⽗类中定义好⽅法. 在这个⽅法中什么都不⽤⼲. 就抛⼀个异常就可以了.
    这样所有的⼦类都必须重写这个⽅法. 否则. 访问的时候就会报错.
    方法1*****
    class payment:
        def pay(self,money):
            raise Exception("子类没有引用pay方法")
            #手动添加报错信息
    class qqpay(payment):
        def pay(self,money):
            print(f"使用QQ支付{money}")
    
    class wechatpay(payment):
        def pay(self,money):
            print(f"使用QQ支付{money}")
    
    class Alipaypay(payment):
        def zhifu(self,money):
            print(f"使用支付支付{money}")
    
    def pay(obj,money):统一接口(支付接口,方便其他文件的互相调用)
        obj.pay(money)
    
    obj1 = qqpay()
    obj2 =wechatpay()
    obj3 =Alipaypay()
    
    pay(obj1,100)
    pay(obj2,100)
    pay(obj3,100)
    
    
    方法2:抽象类,接口类 :强制指定规则
    from abc import ABCMeta,abstractmethod
    class Payment(metaclass=ABCMeta):
        @abstractmethod
        def pay(self,money):
            pass
    class qqpay(Payment):
        def pay(self,money):
            print(f"使用QQ支付{money}")
    
    class wechatpay(Payment):
        def pay(self,money):
            print(f"使用QQ支付{money}")
    
    class (Payment):
        def pay(self,money):
            print(f"使用支付宝支付{money}")
    def pay(obj,money):
        obj.pay(money)
    
    obj1 = qqpay()
    obj2 =wechatpay()
    obj3 =Alipaypay()
    
    pay(obj1,100)
    pay(obj2,100)
    pay(obj3,100)
    

    super深度深入了解

    class A:
        def f1(self):
            print('in A')
    
    class Foo(A):
        def f1(self):
            super().f1()
            print('in Foo')
    
    class Bar(A):
        def f1(self):
            print('in Bar')
    
    class Info(Foo,Bar):
        def f1(self):
            super().f1()
            print('in Info f1')
     print(Info.mro())#  Info--》Foo--》Bar--》A--》object
    
    obj = Info()
    obj.f1()
    1.实例化一个对象
    2.先在info的类中找f1 info中有f1 执行super().f1 去Foo中找f1,打印'in Foo' 在打印 'in Info f1' 按照mro算法的执行顺序向父类中查找
    
    class A:
        def f1(self):
            print('in A')
    
    class Foo(A):
        def f1(self):
            super().f1()
            print('in Foo')
    
    class Bar(A):
        def f1(self):
            print('in Bar')
    
    class Info(Foo,Bar):
        def f1(self):
            super(Foo,self).f1()
            print('in Info f1')
    
    obj = Info()
    obj.f1()
    1.实例化一个对象
    2.先在Info 中找f1 ,执行 super(Foo,self).f1() 到Foo中找f1 在执行Foo中的super().f1() 在到Bar中找f1 打印in Foo 在打印in Info f1 按照mro算法的执行顺序向父类中查找
    Info--》Foo--》Bar--》A--》object
    3.严格按照对象从属于类的mro的顺序,查询下一个类.
    

    类的成员

    1. 细分类的成员
    class C:
        name = '公有静态字段/变量'
        _phone = 15032551128    #私有静态变量
        def __init__(self,name):#特殊方法
            self.name = name
    
        def func(self):          #普通方法
            print(C.name)
    
        def _func(self,name):    #私有方法
            self.name = name
            print('私有方法')
    class d(C):
        def show(self):
            print(C.name)
    
        @classmethod
        def class_func(cls):
            print("类方法")
    
        @staticmethod
        def static_func():
            print("静态方法")
    
        @property
        def prop(self):
            print("属性")
    obj = C("八戒")
    print(obj.name)
    print(C.nunc()
    obj1 = d(1)
    obj1.show()
    
    
    
    1. 类的私有成员
    公有成员,在任何地方都能访问
    私有成员,只有在类的内部才能方法
    静态字段(静态属性)	
       公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
    class C:
    
        name = "公有静态字段"
    
        def func(self):
            print (C.__name)
    
    class D(C):
    
        def show(self):
            print (C.__name)
    
    
    C.name         # 类访问
    obj = C()
    obj.func()     # 类内部可以访问
    obj_son = D()
    obj_son.show() # 派生类中可以访问    
    
    
       私有静态字段:仅类内部可以访问;
    class C:
    
        __name = "私有静态字段"
    
        def func(self):
            print (C.__name)
    
    class D(C):
    
        def show(self):
            print (C.__name)
    
    
    C.__name       # 不可在外部访问
    obj = C()
    obj.__name     # 不可在外部访问
    obj.func()     # 类内部可以访问  
    obj_son = D()
    obj_son.show() #不可在派生类中可以访问 
    
    ***************************************************
    普通字段(对象属性)
    
    1.公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
    class C:
        
        def __init__(self):
            self.foo = "公有字段"
    
        def func(self):
            print(self.foo)  # 类内部访问
    
    class D(C):
        
        def show(self):
            print(self.foo) # 派生类中访问
    
    obj = C()
    obj.foo     # 通过对象访问
    obj.func()  # 类内部访问
    obj_son = D();
    obj_son.show()  # 派生类中访问
    
    
    2.私有普通字段:仅类内部可以访问
    class C:  
        def __init__(self):
            self.__foo = "私有字段"
    
        def func(self):
            print(self.foo)  # 类内部访问
    
    class D(C):
        def show(self):
            print(self.foo) # 派生类中访问
    
    obj = C()
    obj.__foo     # 通过对象访问    ==> 错误
    obj.func()  # 类内部访问        ==> 正确
    obj_son = D()
    obj_son.show()  # 派生类中访问  ==> 错误
    
    
    
    *****************************************************************************************************
     类的私有成员
    1.在类的内部访问
    class A:
        name = "liye"
        __name = "gangge"
        def func(self):
            print(self.name)    #类的内部
            print(self.__name)  #类的内部
    obj = A()
    obj.func()
    
    类的外部不能访问私有方法
    class A:
        name = "liye"
        __name = "gangge"
        def func(self):
            pass
    obj = A()
    print(obj.name)    #liye
    print(A.__name)    #错误
    print(obj.__name)  #错误
    
    类的派生类不能访问
    class A:
        name = '李业'
        __name = '钢哥'
    
    class B(A):
        def func(self):
            print(self.__name)
    
    obj = B()
    # print(obj.__name)
    obj.func()
    
    
    总结:私有对象属性只能在类的内部使用,不能再类外部以及派生类使用.
    
    class A:
        def __init__(self,name,pwd):
            self.name = name
            self.pwd = pwd
        def md5(self):
            self.__pwd = self.__pwd + "123"
    obj = A("八戒",123456)
    print(obj.__pwd) #'A' object has no attribute '__pwd' 错误
    私有成员来说: 当你遇到重要的数据,功能,(只允许本类使用的一些方法,数据)设置成私有成员.
    python所有的私有成员都是纸老虎,形同虚设.
    
    class A:
    
        name = '李业'
        __name = '钢哥'  # 私有类的属性
    
        def __func(self):
            print('in __func')
    
    print(A.__dict__)
    print(A._A__name)#别用
    
    类从加载时,只要遇到类中的私有成员,都会在私有成员前面加上_类名 .
    
    
    类的其他方法
    
    类方法有什么用???
        1. 得到类名可以实例化对象.
        2. 可以操作类的属性.
    class A:
        def func(self):
            print('实例方法')
        @classmethod    #类方法
        def cls_func(cls):
            print(f'cls---->{cls}')#<class '__main__.A'>
            obj = cls()
            print(obj)
            print('类方法')
    print(A) #<class '__main__.A'>
    A.cls_func()
    obj = A()
    obj.cls_func()
    类方法: 一般就是通过类名去调用的方法,并且自动将类名地址传给cls,
    但是如果通过对象调用也可以,但是传的地址还是类名地址
    
    
    创建学生类,只要实例化一个对象,写一个类方法,统计一下具体实例化多少个学生?
    原则上,类方法是将类本身作为对象进行操作的方法,默认有个 cls 参数,可以被类和对象调用
    通过实例化一个对象就执行一次 __init__方法 然后调用add 函数 执行自动加1
    class Student:
    
        count = 0
        def __init__(self,name,id):
            self.name = name
            self.id = id
            Student.add()
    
        @classmethod
        def add(cls):
            print(cls)
            cls.count+=1
    
        @classmethod
        def get(cls):
            return cls.count
    
    obj1 =Student("liye",2542621222)
    obj1 =Student("liye",2542621222)
    obj1 =Student("liye",2542621222)
    print(obj1)
    print(Student.get())
    
    class student:
        count = 0
        def __init__(self,name,id):
            self.name = name
            self.id = id
            student.add()
    
        @classmethod
        def add(cls):
            cls.count += 1
    
            return cls.count
    obj = student("d",252531)
    obj1 = student("d",252531)
    obj2 = student("d",252531)
    print(student.count)
    student.add()
    
    
    静态方法
    class A:
    
        def func(self):
            print('实例方法')
    
    
        @classmethod
        def cls_func(cls):
            pass
    
        @staticmethod
        def static_func():
            print('静态方法')
    
    静态方法是不依赖于对象与类的,其实静态方法就是函数.
    保证代码的规范性,合理的划分.后续维护性高.
    
    @property的组合
    class Foo:
    
        @property
        def bmi(self):
            print("1")
        @bmi.setter
        def bmi(self,v):
            print(2)
        @bmi.deleter
        def bmi(self):
            print(3)
    
    obj = Foo()
    obj.bmi       #不加括号也可以直接调用bmi 函数
    obj.bmi = 666 #操作命令,这个命令并不是改变bmi的值,而知执行被bmi.setter装饰器装饰的函数 得不到返回值(return)
    del obj.bmi   #操作命令,这个命令并不是删除bmi的值,而知执行被bmi.setter装饰器装饰的函数 得不到返回值(return)
    
    
     利用实例化对象的方式设置属性.
    
    class Foo:
        def get_AAA(self):
            print('get的时候运行我啊')
    
        def set_AAA(self,value):
            print('set的时候运行我啊')
    
        def delete_AAA(self):
            print('delete的时候运行我啊')
    
        AAA = property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应
    
    f1=Foo()
    f1.AAA
    f1.AAA='aaa'
    del f1.AAA
    *****************************************************************************************************
    
    
    isinstance(a,b):判断a是否是b类(或者b类的派生类)实例化的对象
    issubclass(a,b): 判断a类是否是b类(或者b的派生类)的派生类
    
  • 相关阅读:
    supervisorctl的安装使用
    react应用多入口配置
    百度编辑器
    formData文件上传
    thymeleaf的内联th:inline(在javascript访问model中的数据)
    浅谈Object.prototype.toString.call()方法
    JS中call()和apply()以及bind()的区别
    Json对象与Json字符串的转化
    全面解析JavaScript中“&&”和“||”操作符(总结篇)
    TortoiseSVN客户端重新设置用户名和密码
  • 原文地址:https://www.cnblogs.com/tangjian219/p/11341951.html
Copyright © 2011-2022 走看看