• python—面向对象编程


    面向对象编程简单来说就是基于对  和 对象 的使用,所有的代码都是通过类和对象来实现的编程就是面向对象编程!

    面向对象的三大特性:封装、继承、多态

    首先创建一个类

    #使用class创建一个School类,类中有个student方法
    class School:
        def student(self):
            pass
    a1=School()

    一、封装

    1、封装:将某些内容先封装到一个地方,等到需要的时候再去调用

    class School:
        def __init__(self,name,age):    #构造方法,创建对象是执行
            self.name=name
            self.age=age
    
    #创建对象a1,a2
    a1=School("zhangsan",18)
    a2=School("lisi",18)

    上面代码实现的就是封装的功能,把各自的name和age分别封装到了self的name和age属性中,就等于被封装到了对象a1和a2中

    类中定义的函数叫做方法,带有__init__的函数称为构造方法,在创建a1,a2对象时会自动执行。

    2、调用:调用有两种方式,通过对象直接调用和通过self间接调用

    通过对象直接调用

    class School:
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def student(self):
            print("name:%s,age:%s"%(self.name,self.age))
    #创建对象a1,a2
    a1=School("zhangsan",18)
    a2=School("lisi",18)
    print a1.name,a1.age
    print a2.name,a2.age
    #执行结果: zhangsan 18
          lisi 18

    通过self间接调用

    class School:
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def student(self):
            print("name:%s,age:%s"%(self.name,self.age))
    #创建对象a1,a2
    a1=School("zhangsan",18)
    a2=School("lisi",18)
    
    #执行类中的方法时,通过self间接调用被封装的内容
    a1.student()
    a2.student()
    #执行结果:
    #name:zhangsan,age:18
    #name:lisi,age:18

    二、继承

    1、继承:既派生类(子类)可以继承基类(父类)的方法,我们可以将多个类共有的方法提取到父类当中,这样子类仅需继承父类而不必一一实现每个方法

    在类名后面括号中写上另一个类,表示继承了那个类

    #使用class创建一个School类
    class School:
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def student(self):
            print("name:%s,age:%s"%(self.name,self.age))
        def classroom(self):
            print("%s去教室"%self.name)
    
    class SchoolA(School):  #SchoolA继承School
        def __init__(self,name):
            self.name=name
    
    class SchoolB(SchoolA): #SchoolB继承SchoolA
        def __init__(self,name):
            self.name=name
    #创建对象a1
    a1=SchoolA("zhangsan")
    a1.classroom()
    #创建对象a2
    a2=SchoolB("lisi")
    a2.classroom()
    
    #执行结果:
    #   zhangsan去教室
    #   lisi去教室

    在上面代码中我们可以看到,在SchoolA和SchoolB中都没有classroom方法,但由于SchoolB继承了SchoolA,而SchoolA又继承了School,所以他们创建对象后都能

    调用School中的classroom方法。

    2、多继承

    在python中,类还可以继承多个类,在继承多个类时,他对类中的函数查找有两种方式

      深度优先:类是经典类时,多继承情况下,会按照深度优先方式查找

      广度优先:类是新式类时,多继承情况下,会按照广度优先方式查找

    (在python3.x中)都默认为广度优先,但还是可以了解一下两个的区别,新式类:当前类或者基类继承了objiect类就叫新式类,否者就是经典类

    在python2.7中

    #python2.7中经典类
    class A():
        def name(self):
            print("AAAAAA")
    class B(A):
        pass
    class C(A):
        def name(self):
            print("CCCCCC")
    class D(B,C):
        pass
    a1=D()
    a1.name()   #输出:AAAAAA
    #查找顺序:# 首先去自己D类中查找,如果没有,则继续去B类中找,没有则继续去A类中找,没有则继续去C类中找,如果还是未找到,则报错
    #深度优先:D-B-A-C
    #python2.7中新式类
    class A(object):
        def name(self):
            print("AAAAAA")
    class B(A):
        pass
    class C(A):
        def name(self):
            print("CCCCCC")
    class D(B,C):
        pass
    a1=D()
    a1.name()   #输出:CCCCCC
    #查找顺序:# 首先去自己D类中查找,如果没有,则继续去B类中找,没有则继续去C类中找,没有则继续去A类中找,如果还是未找到,则报错
    #广度优先:D-B-C-A

    上面两个例子中我们可以看到,经典类和新式类输出的结果是不一样的,是因为他们的查找顺序不一样

    python2.7中 广度优先的前提条件:D继承BC,BC又同时继承A,只有满足这个条件,新式类才会遵循广度优先,否者不会,例:

    class A(object):
        def name(self):
            print("AAAAAA")
    class B(A):
        pass
    class C:
        def name(self):
            print("CCCCCC")
    class D(B,C):
        pass
    a1=D()
    a1.name()   #输出:AAAAAA

    如果C不在继承A,那么就算你是新式类,他也会按照深度优先的顺序查找

    在python3.X之后就没有了上面的这些区别,它的查找顺序都是 广度优先 

    三、多态

    python不支持多态,也用不到多态,python是一种多态语言,崇尚鸭子类型

     四、类中的成员

    类中的成员:字段、方法、属性

    1、字段

    字段:普通字段、静态字段

    class School:
        headmaster="王五"
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def student(self):
            print("name:%s,age:%s"%(self.name,self.age))
    
    #创建对象a1
    a1=School("zhangsan",18)
    print(a1.name)  #访问普通字段
    print(School.headmaster)    #访问静态字段
    
    #执行结果:
    #   zhangsan
    #   王五

    在上面代码中,__init__函数中的就是普通字段,headmaster就是静态字段

      普通字段:属于对象,由对象来访问,在内存中每个对象都要保存一份

      静态字段:属于类,由类直接访问,在内存中只保存一份

    2、方法

    方法:普通方法、静态方法、类方法

    class School:
        headmaster="王五"
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def student(self):  #普通方法 至少一个self
            print("普通方法")
    
        @staticmethod       #静态方法 任意参数
        def classroom():
            print("静态方法")
    
        @classmethod
        def dormitory(cls):    #类方法 只能一个cls
            print("类方法",cls)
    
    #创建对象a1
    a1=School("zhangsan",18)
    a1.student()
    
    School.classroom()    #访问静态方法
    School.dormitory()     #访问类方法
    
    '''执行结果:
        普通方法
        静态方法
        类方法 <class '__main__.School'>
        '''

    普通方法:先创建一个对象,在用对象去调用这个方法

    静态方法:直接用类调用,可以有任意参数(静态方法可以让类直接调用,省去了普通方法创建对象的步骤)

    类方法:直接用类调用,只能一个cls参数

        上面我们可以看到执行类方法时,输出了他传入的参数等于<class '__main__.School'>,是一个类,意思就是执行时,它会把当前的类当成参数传进去。

    3、属性

    属性定义:装饰器定义、静态字段定义

    (1)装饰器定义

    class School:
        headmaster="王五"
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def student(self):  #方法
            print("方法")
    
        @property
        def classroom(self):    #属性,加上@property装饰器,仅有一个self参数
            print("属性")
    
    #创建对象a1
    a1=School("zhangsan",18)
    a1.student()    #调用方法
    a1.classroom    #调用属性
    
    #执行结果:
    #   方法
    #   属性

    在上面代码中可以看到,在方法上加上@property装饰器就叫属性,属性和方法的区别就是调用时不用加括号

    在新式类中,除了@property,还有另外两种装饰器

    class School(object):
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        @property
        def classroom(self):    #属性,加上@property装饰器,仅有一个self参数
            print(self.name,self.age)
        @classroom.setter
        def classroom(self,age):
            self.age=age    #把age修改为传入的参数
            print("修改",self.name,self.age)
        @classroom.deleter
        def classroom(self):
            del self.age        #删除age
            print("删除",self.name,self.age)
    
    #创建对象a1
    a1=School("张三",18)
    a1.classroom    #1.执行后会自动调用@property方法
    a1.classroom=20     #2.执行后会自动调用@classroom.setter的方法,并将20传给age参数
    del a1.classroom    #3.执行后会自动调用@classroom.deleter的方法
    
    '''执行结果:
        张三 18
        修改 张三 20
        在执行3时会报错,因为age已经在@classroom.deleter下面的方法里删除了,所以输出self.age时会出错
    '''

    (2)静态字段定义

    class School(object):
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def classroom(self):
            print(self.name,self.age)
    
        def classroom_update(self,age):
            self.age=age    #把age修改为传入的参数
            print("修改",self.name,self.age)
    
        def classroom_del(self):
            del self.age        #删除age
            print("删除",self.name,self.age)
    
        obj=property(classroom,classroom_update,classroom_del)  #静态字段方式定义属性
    
    #创建对象a1
    a1=School("张三",18)
    a1.obj  #1.执行后会自动调用classroom方法
    a1.obj=20     #2.执行后会自动调用classroom_update的方法,并将20传给age参数
    del a1.obj    #3.执行后会自动调用classroom_delr的方法

    4、公有成员和私有成员

    在类中的每一个成员都有两种形式:公有、私有

    公有:都可以访问      私有:只有在类的内部可以访问

    举几个例子

    字段

    class School(object):
        deg="" #公有静态字段
        __cat=""   #私有静态字段
        def __init__(self,name,age):
            self.name=name  #公有普通字段
            self.__age=age  #私有普通字段
    
        def dormitory(self):
            print(self.__age)
    
        def cat(self):
            print(School.__cat)
    
    #创建对象a1
    a1=School("张三",18)
    #访问普通字段
    print(a1.name)  #输出:张三
    print(a1.age)   #报错,提示没有age,因为age是私有字段,只能间接内部访问
    a1.dormitory()  #只能通过类内部访问私有字段
    #访问静态字段
    print(School.deg)   #输出:狗
    print(School.__cat) #报错
    a1.cat()        #输出:猫   可以间接通过内部的cat方法反问私有静态字段

    方法

    class School(object):
    
        def __init__(self,name,age):
            self.name=name
            self.__age=age
    
        def cat(self):  #公有方法
            print("cat")
    
        def __dog(self):   #私有方法
            print("dog")
    
        def doo(self):  #内部访问私有方法
            a1.__dog()
    #创建对象a1
    a1=School("张三",18)
    a1.cat()    #输出:cat
    a1.dog()    #报错
    a1.doo()    #输出:dog  间接通过doo方法反问私有方法__dog

    类中的其他成员也和上面的类似

    如果想要强制访问私有字段,可以通过(对象._类名__私有字段名)访问,不建议强制访问私有成员。

    5、类中的特殊成员

    (1)__doc__

    class School(object):
        """类的描述信息"""
        def __init__(self,name,age):
            self.name=name
            self.__age=age
    
    print(School.__doc__)   #输出:类的描述信息

    (2)__init__

    在上面已经说过,在创建对象是自动执行

    (3)__del__

    当对象在内存中被释放时,自动触发执行

    (4)__call__

    在创建的对象后面加括号执行时,会自动执行类里的__call__方法

    class School(object):
    
        def __call__(self, *args, **kwargs):
            print("触发__call__方法")
    
    a1=School()
    a1()    #输出:触发__call__方法
    School()()  #输出:触发__call__方法

    (5)__dict__

    获取类或对象的所有成员

    class School(object):
        """类的描述信息"""
        cat=""
        def __init__(self,name,age):
            self.name=name
            self.__age=age
        def dog(self):
            print("dog")
    
    print(School.__dict__)  #获取类中的成员
    a1=School("张三",18)
    print(a1.__dict__)  #获取对象中的成员
    '''
    输出:
    {'cat': '猫', '__init__': <function School.__init__ at 0x000000000226C950>, '__dict__': <attribute '__dict__' of 'School' objects>, '__weakref__': <attribute '__weakref__' of 'School' objects>, '__module__': '__main__', 'dog': <function School.dog at 0x000000000226CAE8>, '__doc__': '类的描述信息'}
    {'name': '张三', '_School__age': 18}
    '''

    (6)__str__

    没有__str__

    class School(object):
        def __init__(self,name,age):
            self.name=name
            self.__age=age
    a1=School("张三",18)
    print(a1)   #输出:<__main__.School object at 0x000000000222B278>

    有__str__

    class School(object):
        def __init__(self,name,age):
            self.name=name
            self.__age=age
    
        def __str__(self):
            return("print对象时的返回值")
    a1=School("张三",18)
    print(a1)   #输出:print对象时的返回值

    其他的特殊成员就不一一列举了,因为大多数情况下也不会用到

    详细请看:http://www.cnblogs.com/wupeiqi/p/4766801.html

  • 相关阅读:
    CSS:命名规范心得分享
    css中用一张背景图做页面的技术有什么优势?
    ie8 css hack
    简单介绍几个CSSReset的方法
    牛人也得看的CSS常识
    DIV+CSS网页布局常用的一些基础知识整理
    font-size:100%有什么作用?
    为什么无法定义1px左右高度的容器
    Div+CSS常见错误总结
    从数字千分位处理认识(?<=)、(?=)、(?:)
  • 原文地址:https://www.cnblogs.com/melonjiang/p/5135101.html
Copyright © 2020-2023  润新知