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

    OOP 面向对象的程序开发

    用几大特征表达一类事物称为一个类,类更像是一张图纸,表达的是一个抽象概念
    对象是类的具体实现,更像是由这图纸产出的具体物品,类只有一个,但对象可以通过这个类实例化出多个
    对象是类的实例,类是对象的模板
    *类中的成员只有方法和属性,不要裸露的把判断和循环直接写在类中,而是用方法包起来

    (1)类的定义
    # 定义一
    class Myclass:
        pass
    
    # 定义二
    class Myclass():
        pass
    
    # 定义三
    class Myclass(object):
        pass
    (2)类的实例化 产生的是对象
    >>> class Car():
    ...   color = "red"
    ...
    >>> obj = Car()
    >>> print(obj)
    <__main__.Car object at 0x0000026497119BE0>
    >>>
    (3)类的基本结构
      1.成员属性
      2.成员方法
    >>> class MyCar():
    ...   # 成员属性
    ...   color = "red"
    ...   # 成员方法
    ...   def run():
    ...     pass
    ...
    >>>
    (4)类的命名
      推荐使用驼峰命令,每个单词首字母大写
      myclass --> MyClass

    面向对象三大特征: 封装 继承 多态

    封装:对类中成员属性和方法的保护,控制外界对内部成员的访问,修改,删除等操作
      对象的使用方式:
        对象.属性
        对象.方法
    class MyCar():
        # 公有成员属性
        attra = "属性"
        # 私有成员属性
        __attrb = "私有属性"
        # 公有成员方法
        def run(self):
            print("调用属性",self.attra)
        # 私有成员方法
        def __private_info(self):
            print("私有成员方法")
    
    """
    绑定方法:
      1.绑定到对象,默认把对象当成参数进行传递,self形参接受
      2.绑定到类,默认把类当成参数进行传递,形参接受
    """
    # 实例化对象
    obj = MyCar()
    
    # 1.实例化的对象防卫公有成员属性和方法
    print(obj.attra)
    obj.run()
    
    # 2.实例化的对象动态添加公有成员属性和方法
    """
    __dict__ 获取对象或者类的内部成员
    """
    print(obj.__dict__) # 当前对象没有成员
    obj.attra = "改变属性"
    print(obj.__dict__)
    
    # 动态添加成员方法
    # 1) 添加无参方法
    def methoda():
        print("新添加的方法1")
    # 类外的函数赋值给obj对象一个成员方法
    obj.methoda = methoda
    obj.methoda()
    print(obj.__dict__)
    
    # 2) 添加有参方法
    def methodb(self,arge):
        print(self.attra,arge)
    # 赋值
    obj.methodb = methodb
    # 需要手动传入对象
    obj.methodb(obj,"有参方法")
    
    # 3) 添加lambda表达式
    obj.methodc = lambda : print("添加方法c")
    obj.methodc()
    
    # -------------------------------
    # 运行结果
    属性
    调用属性 属性
    {}
    {'attra': '改变属性'}
    新添加的方法1
    {'attra': '改变属性', 'methoda': <function methoda at 0x0000020F70DA2EA0>}
    改变属性 有参方法
    添加方法c
    继承
    一个类除了自身所拥有的属性方法之外,还获取了另外一个类的成员属性和方法
       一个类继承另外一个类,当前类是子类(衍生类),被继承的类是父类(基类、超类)。所有类的父类都是object
       单继承
        -1.子类可以使用父类的共有方法
    >>> class Father():
    ...   attra = 'a'
    ...   def func(self):
    ...     print('func')
    ...
    >>> class Son(Father):
    ...   pass
    ...
    >>> obj = Son()
    >>> print(obj.attra)
    a
    >>> obj.func()
    func
    >>>
    

        -2.子类不能调用父类的私有方法

    >>> class Father():
    ...   __attrb = 'b'
    ...   def __func(self):
    ...     print('private func')
    ...
    >>> class Son(Father):
    ...   pass
    ...
    >>> obj = Son()
    >>> obj.__attrb
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Son' object has no attribute '__attrb'
    >>> obj.__func()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Son' object has no attribute '__func'
    >>>
    

        -3.子类可以改写父类方法

          self对象优先调用本类中的方法,如果本类中没有调用父类的

      多继承

    # 基本语法
    class Father():
        attra = "属性a"
        def methoda(self):
            print("methoda")
    
    class Mother():
        attrb = "属性b"
        def methodb(self):
            print("methodb")
    
    class Son(Father,Mother):
        pass
    
    obj = Son()
    print(obj.attra)
    obj.methoda()
    
    # 执行结果
    属性a
    methoda

       类的相关操作

        语法:类.属性  类.方法()

      1.调用类中成员的时候,要么使用对象,要么使用类

          对象可以使用类中的相关公有成员,但是没有归属权

       类中的成员都归当前这个类所有,但是不能使用对象中的成员

      2.对象中如果有成员,使用自己的,如果没有,使用类中的

    class Person():
        attra = "公有成员属性"
        __attrb = "私有成员属性"
        def method():
            print("普通公有方法",Person.__attrb)
        def __private_method():
            print("普通私有方法")
    
    obj = Person() # 实例化一个对象
    print(Person.attra) # 类访问成员属性
    print(Person.method()) # 类访问成员方法
    """
    1.对象无法调用无参的普通方法,必须加上self
    2.无论是对象还是类,都无法在类外调用类中的私有成员
    """
    print(Person.__dict__) # 查看类的所有成员
    
    # 定义的类动态添加公有成员属性和方法
    Person.attrc = "添加成员属性"
    print(Person.__dict__)
    print(obj.__dict__)
    
    # 1) 添加无参方法
    def methoda():
        print("添加无参方法")
    Person.methoda = methoda
    Person.method()
    
    # 2) 添加有参方法
    def methodb(name):
        print("方法",name)
    Person.methodb = methodb
    Person.methodb("有参方法")
    
    # 3) lambda表达式
    Person.methodc = lambda : print("lambda表达式")
    Person.methodc()
    
    # 执行结果
    公有成员属性
    普通公有方法 私有成员属性
    None
    {'__module__': '__main__', 'attra': '公有成员属性', '_Person__attrb': '私有成员属性', 'method': <function Person.method at 0x00000280E4203598>, '_Person__private_method': <function Person.__private_method at 0x00000280E4203488>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
    {'__module__': '__main__', 'attra': '公有成员属性', '_Person__attrb': '私有成员属性', 'method': <function Person.method at 0x00000280E4203598>, '_Person__private_method': <function Person.__private_method at 0x00000280E4203488>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None, 'attrc': '添加成员属性'}
    {}
    普通公有方法 私有成员属性
    方法 有参方法
    lambda表达式

    多态:不同的子类对象,调用相同的父类方法,产生不同的执行结果
       好处:多态是针对对象来说的,在不改变原有代码的前提下,完成不同的功能。不同的对象,调用相同的方法,达到不同的功能
    # 定义一个父类
    class Father():
        # 方法
        def methoda(self):
            pass
    
    # 定义子类调用父类方法
    class Sona(Father):
        def methoda(self):
            print("调用父类,定制化子类a")
    
    class Sonb(Father):
        def methoda(self):
            print("调用父类,定制化子类b")
    
    # 实例化
    obja = Sona()
    objb = Sonb()
    listvar = [obja,objb]
    for i in listvar:
        i.methoda()
    
    # 执行结果
    调用父类,定制化子类a
    调用父类,定制化子类b

    python对成员的保护分为两个等级

    私有的: private
    在本类内部可以访问,类的外部不可以访问.(python中 属性或者方法前面加上两个下划线__)
    公有的: public
    在本类的内部和外部都可以访问.
    (了解)在其他高级语言当中,如java php c++等语言,有三个等级 private public protected
     私有成员的改名策略 [_类名__成员名]
    对象的相关操作
      (1)实例化的对象访问公有成员属性和方法
      (2)实例化的对象动态添加公有成员属性和方法
      (3)实例化的对象删除公有成员属性和方法
    类的相关操作
      (1)定义的类访问公有成员属性和方法
      (2)定义的类动态添加公有成员属性和方法
      (3)定义的类删除公有成员属性和方法
       
    普通方法: 没有任何参数传递,只能类调用
    绑定方法: 把默认传参的方法叫做绑定方法,绑定到对象(默认传对象),绑定到类(默认传类)
    非绑定方法:静态方法(无需传任何参数,对象和类都能调用)
    私有的:只能载类或者对象的结构中访问
    公有的:可以载任何位置访问
    受保护:可以载当前类或者对象 和子类或者子类对象中访问

    类内   子类中   类外部
    公有的: √       √       √  
    私有的: √       X       X
    受保护: √       √       X (python语言不支持)

    编程语言的发行时间

    1972    C
    1983 C++(即带有类概念的C语言,更名于1983年7月)
    1989 Python
    1991 Visual Basic
    1993 Ruby
    1995 JavaScript
    1995 PHP
    1996 Java
    2001 C#
    2009 Go


    多继承弊端

    多继承的弊端会造成菱形继承这种情况,找不清调用顺序
    super对象按照mro列表的顺序依次调用,解决菱形继承存在的问题

    经典类:深度优先 (python2.x)
    新式类:广度优先 (python3.x)

    写多继承时,尽量避免造成不同类相同方法名的情况,提高代码质量 高内聚,低耦合
    高内聚:一个模块只完成一个任务,专一性高
    低耦合:模块与模块之间可以彼此独立不冲突,方便移植复用.

    super调用父类方法

    (1)super本身是一个类 super()是一个对象 用于调用父类的绑定方法
    (2)super() 只应用在绑定方法中,默认自动传递self对象 (前提:super所在作用域存在self)
    (3)super用途: 解决复杂的多继承调用顺序
    class Father():
        attra = "aaa"
        def methoda():
            print("aaa")
    
    class Mother():
        attrb = "bbb"
        def methodb(self):
            print("bbb")
    
    class Son(Father,Mother):
        attra = "s-aaa"
        def methodb(self):
            print("s-bbb")
        def calla(self):
            print(Father.attra)
            Father.methoda()
        """
        self在调用时,本类有,优先调用自己,本类没有,调用父类
        """
        def callb(self):
            print(self.attrb)
            self.methodb()
        def callc(self):
            print(super().attra)
            super().methodb()
    
    obj = Son()
    obj.calla()
    obj.callb()
    obj.callc()
    
    # 执行结果
    aaa
    aaa
    bbb
    s-bbb
    aaa
    bbb

    魔术方法(特定时机自动触发)

    __init__魔术方法(构造方法)
    '''
    触发时机:实例化对象,初始化的时候触发
    功能:为对象添加成员
    参数:参数不固定,至少一个self参数
    返回值:无
    '''
    # 基本语法
    class MyClass():
        def __init__(self):
            self.name = "Python"
    
    obj = MyClass()
    print(obj.name)
    
    # 多个参数的__init__
    class MyClass():
        def __init__(self,name):
            self.name = name
    
    obj = MyClass("Python")
    print(obj.name)
    
    # 综合
    class MyClass():
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def score(self):
            print("-->111")
        def course(self):
            print("-->222")
    obj = MyClass("Python",18)
    obj.score()
    obj.course()
    
    # 执行结果 
    Python
    Python
    -->111
    -->222 
    __new__ 魔术方法
    '''
    触发时机:实例化类生成对象的时候触发(触发时机在__init__之前)
    功能:控制对象的创建过程
    参数:至少一个cls接受当前的类,其他根据情况决定
    返回值:通常返回对象或None
    '''
    # 可以通过__new__来控制对象创建的过程
    class MyClassa():
        attra = 'a'
    obja = MyClassa()
    
    class MyClassb():
        def __new__(cls, *args, **kwargs):
            print(cls) # 通过父类object 中的 __new__ 魔术方法 ,返回该类的对象,参数是类
            return obja # 可以返回别人的对象
    
    objb = MyClassb()
    print(objb)
    print(obja.attra)
    __new__和__init__之间的区别
    """
    __new__ 创建对象
    __init__ 初始化对象
    __new__ 在 __init__触发之前
    """
    class MyClass():
        def __new__(cls,name): # __new__和__init__形参和实参要匹配
            print(111)
            return object.__new__(cls) # 需要返回给__init__中参数
        def __init__(self,name):
            print(222)
            self.name = name
    
    obj = MyClass("test")
    print(obj.name)
    
    # 升级
    class MyClass():
        def __new__(cls, *args, **kwargs):
            print(111)
            return object.__new__(cls)
        def __init__(self,name,age,sex):
            print(222)
            self.name = name
            self.age = age
            self.sex = sex
    
    obj = MyClass("A",22,"M")
    print(obj.name)
    
    # __init__只会初始化自己的对象
    class MyClassa():
        def __new__(cls, *args, **kwargs):
            print(111)
            return obj
        def __init__(self):
            print(222)
    
    obj = MyClassa()
    print(obj)
    
    # 执行结果
    111
    222
    test
    111
    222
    A
    111
    <__main__.MyClass object at 0x000002AD34F1E1D0> 
    __del__ 魔术方法(析构方法)
    触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候]
      功能:对象使用完毕后资源回收
    参数:一个self接受对象
    返回值:无
    1.执行完毕触发析构方法
    class Del():
        def __init__(self,name):
            self.name = name
    
        def splitline(self):
            print('-----')
    
        def __del__(self):
            print('析构方法触发')
    
    obj = Del('析构方法测试')
    # 1.执行完毕触发析构方法
    print('--程序执行完毕--')
    
    # 执行结果
    --程序执行完毕--
    析构方法触发
    

     2.所有对象被del后触发

    class Del():
        def __init__(self,name):
            self.name = name
    
        def splitline(self):
            print('-----')
    
        def __del__(self):
            print('析构方法触发')
    
    obj1 = Del('析构方法测试')
    print('--程序执行完毕start--')
    obj2 = obj1
    del obj1
    del obj2 # 此处不执行del则在最后触发析构方法
    print('--程序执行完毕end--')
    

     3.例:文件读取操作(应用)

    class ReadFile():
        def __new__(cls,filename):
            if os.path.exists(filename):
                return object.__new__(cls)
            return print("改文件不存在")
                
        def __init__(self,filename):
            self.fp = open(filename,mode="r",encoding="utf-8")
            
        def readcontent(self):
            res = self.fp.read()
            return res
            
        def __del__(self):
            self.fp.close()
    
    obj = ReadFile("ceshi111.txt")
    res = obj.readcontent()
    print(res)
    __call__ 魔术方法
    '''
    触发时机:把对象当作函数调用的时候自动触发
    功能: 模拟函数化操作
    参数: 参数不固定,至少一个self参数
    返回值: 看需求
    '''
    # 统一调用
    class MyClass():
        def __call__(self,task):
            print("统一调用{}".format(task))
            self.step1()
            self.step2()
            self.step3()
        def step1(self):
            print(111)
        def step2(self):
            print(222)
        def step3(self):
            print(333)
    
    obj = MyClass()
    obj('test')
    
    # 执行结果
    统一调用test
    111
    222
    333 
    __str__ 魔术方法
    '''
    触发时机: 使用print(对象)或者str(对象)的时候触发
    功能:     查看对象
    参数:     一个self接受当前对象
    返回值:   必须返回字符串类型
    '''
    class MyClass():
        attra = 'attra'
        def __init__(self,name):
            self.name = name
        def info(self):
            return "测试属性{},测试名称{}".format(self.attra,self.name)
        def __str__(self):
            return self.info()
    
    obj = MyClass("test")
    # 打印时触发
    print(obj) # 没有__str__时 :<__main__.MyClass object at 0x000001F1DEACA208>
    print(obj) # 有__str__时 :测试属性attra,测试名称test 
    __repr__ 魔术方法
    '''
    触发时机: 使用repr(对象)的时候触发
    功能:     查看对象,与魔术方法__str__相似
    参数:     一个self接受当前对象
    返回值:   必须返回字符串类型
    '''
    class MyClass():
        attra = "attra"
        def __init__(self,name):
            self.name = name
        def info(self):
            return "属性{},名称{}".format(self.attra,self.name)
        def __repr__(self):
            return self.info()
        # 系统底层自动添加下面语句
        __str__ = __repr__
    
    obj = MyClass("test")
    print(obj)
    print(str(obj)) 
    ----普通变量的基本操作,如果应用在对象上,也有相应的魔术方法

    __bool__ 魔术方法
    '''
    触发时机:使用bool(对象)的时候自动触发
    功能:强转对象
    参数:一个self接受当前对象
    返回值:必须是布尔类型
    '''
    class MyClass():
        def __bool__(self):
            return False 
            
    # 实例化对象
    obj = MyClass()        
    res = bool(obj)
    print(res)
    '''
    类似的还有如下等等(了解):
    __complex__(self)     被complex强转对象时调用
    __int__(self)         被int强转对象时调用
    __float__(self)       被float强转对象时调用
    ...
    ...
    '''
    __add__ 魔术方法  (与之相关的__radd__ 反向加法)
    '''
    触发时机:使用对象进行运算相加的时候自动触发
    功能:对象运算
    参数:二个对象参数
    返回值:运算后的值
    '''
    class MyClass():
        def __init__(self,num):
            self.num = num
            
        # 当对象在+加号的左侧时,自动触发;
        def __add__(self,other):
            return self.num * 2 + other
            
        # 当对象在+加号的右侧时,自动触发
        def __radd__(self,other):
            return self.num * 3 + other
    
    a = MyClass(3)
    # self 接收到 a ,other 接收到 1 self.num * 2 + 1 = 3 * 2 +1 = 7
    res = a+1
    print(res)
    
    
    b = MyClass(5)
    # 第一次参数永远接受的是对象,self接收的 b ,other 接受的是 2 => 5 * 3 + 2 => 17
    res = 2 + b
    print(res)

    '''
    类似的还有如下等等(了解):
    __sub__(self, other)           定义减法的行为:-
    __mul__(self, other)           定义乘法的行为:
    __truediv__(self, other)       定义真除法的行为:/
    ...
    ...
    '''
    __len__ 魔术方法
    '''
    触发时机:使用len(对象)的时候自动触发
    功能:用于检测对象中或者类中某个内容的个数
    参数:一个self接受当前对象
    返回值:必须返回整型
    '''
    # 计算类中的成员个数
    class MyClass():
        pty1 = 1
        __pty2 = 2
        pty3 = 3
        
        def func1(self):
            pass
        
        def func2(self):
            pass
            
        def __func3(self):
            pass
            
        def __len__(self):
            dic = MyClass.__dict__
            """
            lst = []        
            for i in dic:
                if not( i.startswith("__") and i.endswith("__") ):
                    lst.append(i)
            """
            lst = [i for i in dic if not( i.startswith("__") and i.endswith("__") )]
            return len(lst)
    
    obj =  MyClass()
    print(len(obj))
    '''
    类似的还有如下等等(了解):
    __iter__(self)                 定义迭代容器中的元素的行为
    __reversed__(self)             定义当被 reversed() 调用时的行为
    __contains__(self, item)       定义当使用成员测试运算符(in 或 not in)时的行为
    ...
    ...
    ''' 


    反射

     概念:通过字符串去操作类对象 或者 模块中的属性方法
     (1)类中的反射
    hasattr() 检测对象/类是否有指定的成员
    getattr() 获取对象/类成员的值
    setattr() 设置对象/类成员的值
    delattr() 删除对象/类成员的值

     (2)模块的反射
    sys.modules 返回一个系统字典,字典的键是加载的所有模块

    class Myclass():
        attra = '属性a'
        __attrb = "私有属性b"
        def methoda():
            print("普通方法")
        def methodb(self):
            print("绑定方法")
        def __methodc(self):
            print("私有方法")
    
    obj = Myclass()
    # 1.hasattr() 检测对象/类是否有指定的成员
    print(hasattr(obj,"attra"))
    print(hasattr(Myclass,'attra'))
    
    # 2.getarrt() 获取对象/类成员的值
    print(getattr(obj,"attra"))
    getattr(obj,"methodb")()
    
    # 3.setarrt() 设置对象/类成员的值
    setattr(obj,"attrc","属性c")
    print(obj.attrc)
    
    # 4.delattr() 删除对象/类成员的值
    delattr(obj,"attrc")
  • 相关阅读:
    jQuery入门教程
    vue-lazyload 图片不更新
    Eggjs 设置跨域请求
    Vue.js错误: Maximum call stack size exceeded
    ubuntu nginx ssl 证书配置
    ubuntu 安装nginx, 出现 Unable to locate package
    nginx 判断移动端或者PC端 进入不同域名
    node.js 生成二维码
    Linux 配置ssh 免密码登录
    nodejs 从部署到域名访问
  • 原文地址:https://www.cnblogs.com/wangzihong/p/11297496.html
Copyright © 2011-2022 走看看