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

    面向对象和面向过程

    面向对象的三个主要特征:封装、继承、多态。

    面向过程编程:函数式编程,C程序等

    面向对象编程:C++,JAVA,Python等

    类和对象

    类和对象是面向对象中的两个很重要的概念。

    类:是对事物的抽象,比如 人类、球类。类还有属性:比如人的眼耳口鼻。还有方法:吃穿住行。静态属性,动态方法。

    对象:是对类的一个实例,比如足球、篮球

    面向对象的主要思想:封装、继承、多态。这种思想方便解决较为复杂的项目,且维护起来较为容易。

    python类的定义:

    数字字母下划线组成的,不能以数字开头。定义变量是小写,两个单词则是下划线连接。函数的话则是第二个单词之后是大写字母开头。类的话是每个首字母大写。这样定义根据名称就可以知道是函数还是类。

    类把需要的变量和函数组合成一起,这种包含成为”封装“。" class A(object): "

    类的结构:

    class类名:

        成员变量 - 属性

        成员函数 - 方法

    通过对象访问属性:color是属性,所以后面没有括号

    #@File :demo_lei.py
    class People(object):
        color = 'yellow'            \这也是静态属性
    ren = People()
    print ren
    print ren.color
    <__main__.People object at 0x02CC9FD0>  \返回值带尖括号的,就是类
    yellow                   \通过对象访问属性的返回值
    类的定义

    定义动态方法:方法中至少有一个参数是self。调用方法时,需要加括号。

    #@File :demo_lei.py
    class People(object):
        color = 'yellow'
        def think(self):
            print "I am a thinker"
    ren = People()
    ren.think()                            \方法的调用需要使用括号。
    返回值
    I am a thinker
    

      实例化:把类赋值给变量,变量的类型就是一个对象。通过对象访问类里面的属性和方法。

    类的属性:

    首先:对象的创建

    创建对象的过程称之为实例化;当一个对象被创建之后,包含三个方面的特性:对象句柄、属性和方法。句柄用于区分不同的对象。对象的属性和方法与类中的成员变量和成员函数对应。

    类的属性:类的属性按使用范围分为公有属性和私有属性,类的属性范围取决于属性的名称。

    公有属性:在类中和类外都能调用的属性。

    私有属性:不能再类外及类意外的函数调用。定义方式:以“__”双下划线开始的成员变量就是私有属性。可以通过instance._classname__attribute方式访问。

    内置属性:由系统在定义类到时候默认添加的,由前后双下划线构成,__dict__,__module__。

    #@File :demo_lei.py
    class People(object):
        color = 'yellow'
        __age = 20
        def think(self):
            print "I am a thinker"
            print self.__age
    ren = People()
    ren.think()
    print ren.__age
    
    I am a thinker
    Traceback (most recent call last):
    20
      File "C:/Users/xiaojingjing/PycharmProjects/untitled1/liziyan/demo_lei.py", line 18, in <module>
        print ren.__age
    AttributeError: 'People' object has no attribute '__age'
    对象创建

    这里就是私有属性的创建及调用。

     !!!测试过程中可以使用这种方法:私有属性就是为了保护仅在内部调用,所以在正常程序中不建议这么使用。

    print ren._People__age      可以正常打印出返回值!

     当类实例化之后,可以通过实例过后的对象  对类的属性进行修改

     

    #@File :demo_lei.py
    class People(object):
        color = 'yellow'
        __age = 20
        def think(self):
            print "I am a thinker"
            print self.__age
    ren = People()
    ren.think()
    print ren.__dict__
    print People.__dict__
    返回值:
    I am a thinker
    20
    {}    \这里与预期有出入,至少应该返回:{’color‘: ’yellow‘}的,问题没有找到。
    {'__module__': '__main__', 'color': 'yellow', '__doc__': None, '__dict__': <attribute '__dict__' of 'People' objects>, '_People__age': 20, '__weakref__': <attribute '__weakref__' of 'People' objects>, 'think': <function think at 0x034278F0>}
    
        
    

      

    类的方法:

    方法的定义和函数一样,但是需要self作为第一个参数。与类的属性类似,类的方法有:公有方法、私有方法、类方法、静态方法。

     共有方法:在类中和类外都能调用的方法。

    私有方法:不能被类的外部调用,在方法前面加上”__“双下划线就是私有方法。

    self参数:用于区分函数和类的方法(必须有一个self),self参数表示执行对象本身。

     类方法 -- 动态方法:被classmethod()函数处理过的函数,能被类所调用,也能被对象所调用(是继承的关系)

    通过类访问访问其中的方法,称为动态方法:通过类访问方法占用的资源是少的,因为除了调用需要的方法(self以及其他在该方法中定义的属性操作等)外,其他的方法是不会被加载的。

    如果需要直接使用类名来调用方法而不借助实例对象,可以使用classmethod函数实现,方法如下:
    #@File :demo_lei.py
    class People(object):
        color = 'yellow'
        __age = 20
        def test(self):
            print "Testing..."
        cm = classmethod(test)
    jack = People()
    People.cm()
    People.test()
    
    Testing...
    Traceback (most recent call last):
      File "C:/Users/xiaojingjing/PycharmProjects/untitled1/liziyan/demo_lei.py", line 24, in <module>
        People.test()
    TypeError: unbound method test() must be called with People instance as first argument (got nothing instead)
    动态方法

    静态方法:相当于“全局变量“,可以被类直接调用,可以被所有实例化对象共享,通过staticmethod()定义,静态方法没有”self"参数

    首先设置静态方法的方式是:定义的时候不需要使用self参数,但是需要staticmethod函数处理。

    #@File :demo_lei.py
    class People(object):
        color = 'yellow'
        __age = 20
        def test():
            print "Testing..."
        sm = staticmethod(test)
    jack = People()
    People.sm()
    
    Testing...
    静态方法

    通过上述两个例子看出动态方法与静态方法的输出是一样的,但是其中的运行机制却是不同的:

    动态方法是需要谁才会加载谁到内存中,所以是省资源但是效率低;静态方法因为没有(self)所以加载时就会加载所有的方法,占资源但是执行效率高。

     当静态方法需要调用类中的其他成员:

    #@File :demo_lei.py
    class People(object):
        color = 'yellow'
        __age = 20
        def static():
            print "This is static"
            print People.color
        def dongtai(self):
            print 'this is dongtailei'
            print self.color
        cm = classmethod(dongtai)
        sm = staticmethod(static)
    jack = People()
    People.sm()
    People.cm()
    
    This is static
    yellow
    this is dongtailei
    yellow
    

      除了使用以上说的两个函数来处理动态方法静态方法,还可以使用装饰器:

    装饰器:

     装饰器也可以自己写,这里暂时没有涉及。简单学会使用即可。

        @classmethod            #装饰器表示这个方法可以被类调用
        def classFun(self):
            print self.name,
            print "我是类方法"
        @staticmethod
        def staticFun():        #静态方法与动态方法不同,定义时不需要使用self
            print MyClass.name,
            print "我是静态方法"
    
    使用装饰器使得该方法可以被调用。
    装饰器

    python内部类:

    内部类就是类的嵌套:在类里面再创建类。

    #@File :demo_lei.py
    class People(object):
        color = 'yellow'
        __age = 20
    
        class Chinese(object):
            print 'I am Chinese'
            name = 'zhe shi neibulei shuxing'
    
    jack = People()         \这里也可以直接实例化对象为jack = People.Chinese,之后直接打印jack.name
    print jack.Chinese.name
    
    I am Chinese
    zhe shi neibulei shuxing
    内部类的使用

    __str__:类似这样的双下划线开头结尾的成为类的内置方法或魔术方法。

    #@File :demo_lei.py
    class People(object):
        color = 'yellow'
        __age = 20
    
        # def __str__(self):
        #     return "this is People-class"
    
        class Chinese(object):
            print 'I am Chinese'
            name = 'zhe shi neibulei shuxing'
    
    ren = People()
    print ren
    
    I am Chinese
    <__main__.People object at 0x037D9030>
    可见这里的显示并不友好,可以对代码进行修改:上述代码注释部分打开后重新执行:
    I am Chinese
    this is People-class
    

      

    构造函数和析构函数:

    构造函数:用于初始化类的内部状态,python提供的构造函数是:__init__();该方法是可选的,如果不提供,python会给出一个默认的 __init__方法。

    析构函数:用于释放对象占用的资源,python提供的析构函数是__del__();该函数也是可选的,如果不提供,则python会在后台提供默认的析构函数。

    #@File :demo_lei.py
    class People(object):
        color = 'yellow'
        __age = 20
        def __str__(self):
            return "this is People-class"
        def __init__(self):
            self.color = 'black'
        class Chinese(object):
            print 'I am Chinese'
            name = 'zhe shi neibulei shuxing'
    ren = People()
    print ren.color
    print People.color
    
    I am Chinese
    black
    yellow
    这里看出构造函数也是不需要调用自动执行的,触发执行则是通过实例化对象实现的。如果不实例化对象,直接使用类调用,则不会触发初始化。
    构造函数

    初始化函数不仅可以放属性,还可以放方法:

    #@File :demo_lei.py
    class People(object):
        color = 'yellow'
        __age = 20
        def __str__(self):
            return "this is People-class"
        def __init__(self, c='white'):
            self.color = c
            self.think()
        def think(self):
            print ('I am a thinker')
        class Chinese(object):
            # print 'I am Chinese'
            name = 'zhe shi neibulei shuxing'
    ren = People('green')
    print ren.color
    print People.color
    
    I am a thinker
    green
    yellow
    初始化函数里放方法

    析构函数:脚本结束之后才会执行,主要是释放资源。其实即使没有这个函数,python中还有个垃圾回收机制

    #@File :demo_lei.py
    class People(object):
        color = 'yellow'
        __age = 20
        def __init__(self, c='white'):
            self.color = c
            self.fd = open('C:YouKuAaa.txt')
        def __del__(self):
            print 'Del...'
            self.fd.close()
    
    ren = People()
    print People.color
    print 'main end'
    
    yellow
    main end
    Del...
    析构函数调用的时间

    由上面脚本可以看出 __del__ 结束之后才会执行,主要是释放资源。其实即使没有这个函数,python中还有个垃圾回收机制。

     python的垃圾回收站机制:

     python采用垃圾回收机制来清理不再使用的对象;python提供gc模块释放不再使用的对象

    python采用“引用计数”的算法方式来处理回收,即:当某个对象在其作用域中不再被其他对象引用的时候,python就自动清除对象;

    gc模块的collect()可以一次性收集所有待处理的对象(gc.collect)

    #@File :demo_lei.py
    import gc
    class People(object):
        color = 'yellow'
        __age = 20
        def __init__(self, c='white'):
            self.color = c
            self.fd = open('C:YouKuAaa.txt')
        def __del__(self):
            print 'Del...'
            self.fd.close()
    print gc.collect()
    ren = People()
    print People.color
    print 'main end'
    
    0
    yellow
    main end
    0
    Del...
    gc.collect()

    该模块方法的返回值为0则为没有需要回收的文件。这个模块在后台做清理工作,所以这部分一般不需要我们再关心了。

    类的继承:

    继承是面向对象的重要特性之一;

    继承关系:是相对两个类而言的父子关系,子类继承了父类的所有共有属性和方法。

    继承实现了代码的重用。

    继承可以重用已经存在的数据和行为,减少代码的重复编写。python再类名后使用一对括号来表示继承关系,括号中的类即为父类。

    #@File :demo_lei.py
    import gc
    class People(object):
        color = 'yellow'
        def __init__(self, c):
            print "Init..."
            self.dwell = 'Earth'
        def think(self):
            print "I am a %s" % self.color
            print "I am a thinker"
    class Chinese(People):
        def __init__(self):
            People.__init__(self, 'red')
        pass
    cn = Chinese()
    
    Init...
    类的继承

    格式:class Myclass(ParentClass)

    这里的重点:父类定义了 __init__方法(我理解是父类对__init__方法进行了加工,不是采用__init__默认的格式,不然没必要重新定义所以),子类必须显式调用父类的 __init__方法:ParentClass.__init__(self, [args...])如果子类需要扩展父类的行为,可以添加 __init__方法的参数。注意定义父类时,要使用class Parent(object),new style方式来定义,否则继承会报错。

    还可以使用super函数继承父类:这里需要牢记super的语法格式结构!

    #@File :demo_lei.py
    import gc
    class People(object):
        color = 'yellow'
        def __init__(self, c):
            print "Init..."
            self.dwell = 'Earth'
    class Chinese(People):
        def __init__(self):
            # People.__init__(self, 'red')
            super(Chinese, self).__init__('red')
        pass
    cn = Chinese()
    
    Init...
    使用super继承父类继承__init__

    继承__init__初始化函数更推荐使用super来进行类的集成,因为super有很大的优势:自动识别到父类不需要手动输入父类名称,如果修改父类名称,可以省略很多工作量。

    有了父类,子类中可以节省代码重复,还可以增加自己需要的方法

    #@File :demo_lei.py
    import gc
    class People(object):
        color = 'yellow'
        def __init__(self, c):
            print "Init..."
            self.dwell = 'Earth'
        def think(self):
            print "This is Parent`s think"
    class Chinese(People):
        def __init__(self):
            # People.__init__(self, 'red')
            super(Chinese, self).__init__('red')
        def talk(self):
            print "I like talking"
        # def think(self):
        #     print "child`s think"
    cn = Chinese()
    cn.talk()
    cn.think()
    
    Init...
    I like talking
    This is Parent`s think
    子类增加自己的方法,并调用父类的方法

    甚至是修改父类的方法,为己所有。

    #@File :demo_lei.py
    import gc
    class People(object):
        color = 'yellow'
        def __init__(self, c):
            print "Init..."
            self.dwell = 'Earth'
        def think(self):
            print "This is Parent`s think"
    class Chinese(People):
        def __init__(self):
            # People.__init__(self, 'red')
            super(Chinese, self).__init__('red')
        def talk(self):
            print "I like talking"
        def think(self):
            print "child`s think"
    cn = Chinese()
    cn.talk()
    cn.think()
    
    Init...
    I like talking
    child`s think
    修改父类中的方法,为己所用

    多重继承:

    python支持多重继承,即一个类可以继承多个父类:语法 class childnam(parent_1,Parent_2,...)

    #@File :demo_lei.py
    class People(object):
        color = 'yellow'
        def __init__(self):
            print "Init..."
            self.dwell = 'Earth'
        def think(self):
            print "I am a %s" % self.color
            print "My home is %s" % self.dwell
    class Martian(object):
        color = 'red'
        def __init__(self):
            self.dwell = 'Martian'
    # class Chinese(People, Martian):
    class Chinese(Martian, People):
        def __init__(self):
            super(Chinese, self).__init__()
            # People.__init__(self)
    cn = Chinese()
    cn.think()
    
    I am a red
    My home is Martian
    多重继承

    其中要注意,子类继承父类的__init__方法时,尤其是多重继承需要修改前后位置的情况,如果没有super一定要记得修改父类的名称。实验过程中,就因为忘记而出现问题,得到的结果不正确的情况。所以这种情况,推荐super。

    需要注意到是:当父类中出现多个自定义的__init__方法时,多重继承只执行第一个类的__init__方法,其他不执行。但是注意下面这个例子:

    #@File :demo_lei.py
    class People(object):
        color = 'yellow'
        def __init__(self):
            print "Init..."
            self.dwell = 'Earth'
            self.color = 'yellow'
        def think(self):
            print "I am a %s" % self.color
            print "My home is %s" % self.dwell
    class Martian(object):
        color = 'red'
        def __init__(self):
            self.dwell = 'Martian'
    # class Chinese(People, Martian):
    class Chinese(Martian, People):
        def __init__(self):
            # super(Chinese, self).__init__()
            People.__init__(self)
    cn = Chinese()
    cn.think()
    
    Init...
    I am a yellow
    My home is Earth
    指定继承的__init__

    总结:

    类的属性-总结:

    var5 = '全局变量 var5'
    class MyClass(object):
        var1 = '类属性,类的共有属性 var1'
        __var2 = '类的私有属性 __val2'
        def func1(self):
            self.var3 = '对象的公有属性 var3'
            self.__var4 = '对象的私有属性 __var4'
            var5 = '函数的局部变量 var5'
            print self.__var4
            print var5
            # var6 = print '__var2'
        def func2(self):
            print self.var1
            print self.__var2
            print self.var3
            print self.__var4
            print var5
    mc = MyClass()
    print mc.var1
    print mc._MyClass__var2
    mc.func1()
    print mc.var3
    print('#####################    私有属性测试     ############')
    mc.func2()
    print('####    类的内置属性测试,分别通过对象和类调用     ############')
    print mc.__dict__
    print MyClass.__dict__
    
    类属性,类的共有属性 var1
    类的私有属性 __val2
    对象的私有属性 __var4
    函数的局部变量 var5
    对象的公有属性 var3
    #####################    私有属性测试     ############
    类属性,类的共有属性 var1
    类的私有属性 __val2
    对象的公有属性 var3
    对象的私有属性 __var4
    全局变量 var5
    ####    类的内置属性测试,分别通过对象和类调用     ############
    {'_MyClass__var4': 'xe5xafxb9xe8xb1xa1xe7x9ax84xe7xa7x81xe6x9cx89xe5xb1x9exe6x80xa7 __var4', 'var3': 'xe5xafxb9xe8xb1xa1xe7x9ax84xe5x85xacxe6x9cx89xe5xb1x9exe6x80xa7 var3'}
    {'func2': <function func2 at 0x032778F0>, '__module__': '__main__', 'var1': 'xe7xb1xbbxe5xb1x9exe6x80xa7xefxbcx8cxe7xb1xbbxe7x9ax84xe5x85xb1xe6x9cx89xe5xb1x9exe6x80xa7 var1', '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, 'func1': <function func1 at 0x03277970>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '_MyClass__var2': 'xe7xb1xbbxe7x9ax84xe7xa7x81xe6x9cx89xe5xb1x9exe6x80xa7 __val2', '__doc__': None}
    类的属性总结

    类的方法-总结:

    #@File :demo_lei_fangfa.py
    class MyClass(object):
        name = 'Test'
    
        def func1(self):
            print self.name,    #这里结尾没有','则会分行显示!
            print "我是公有方法"
            self.__func2()
        def __func2(self):
            print self.name,
            print "我是私有方法"
        @classmethod            #装饰器表示这个方法可以被类调用
        def classFun(self):
            print self.name,
            print "我是类方法"
        @staticmethod
        def staticFun():        #静态方法与动态方法不同,定义时不需要使用self
            print MyClass.name,
            print "我是静态方法"
    mc = MyClass()
    mc.func1()
    MyClass.classFun()
    MyClass.staticFun()
    
    Test 我是公有方法
    Test 我是私有方法
    Test 我是类方法
    Test 我是静态方法
    类的公有方法与类的私有方法

    类的内置方法:

    #@File :demo_lei_fangfa.py
    class MyClass(object):
        name = 'Test'
        def __init__(self):     #初始化程序。
            self.func1()
            self.__func2()
            self.classFun()
            self.staticFun()
        def func1(self):
            print self.name,    #这里结尾没有','则会分行显示!
            print "我是公有方法"
            # self.__func2()
        def __func2(self):
            print self.name,
            print "我是私有方法"
        @classmethod            #装饰器表示这个方法可以被类调用
        def classFun(self):
            print self.name,
            print "我是类方法"
        @staticmethod
        def staticFun():        #静态方法与动态方法不同,定义时不需要使用self
            print MyClass.name,
            print "我是静态方法"
    mc = MyClass()              #这里可以算是类的实例化,由于__init__是初始化,所以程序执行时就将__init__下面的程序都执行了。
    
    
    Test 我是公有方法
    Test 我是私有方法
    Test 我是类方法
    Test 我是静态方法
    关于类的私有属性
    人不努力的时候,老天是会一点点把你的天赋收走的。
  • 相关阅读:
    INT最值
    约瑟夫问题
    word里的图片怎么复制出来
    必须掌握的8个dos命令
    vld(Visual Leak Detector 内存泄露检测工具
    sscanf,sscanf_s及其相关用法
    游戏开发梦开始的地方笔记
    关于字符编码,你所需要知道的
    CreateMutex创建互斥体可以用于只运行进程的一个实例
    sprintf,你知道多少?
  • 原文地址:https://www.cnblogs.com/shiyan1sheng/p/7844515.html
Copyright © 2011-2022 走看看