zoukankan      html  css  js  c++  java
  • python类的成员和装饰器

    python类的成员和装饰器

    Python类的成员

    Python和c++一样,可以定义类,可以继承,类中又包含了类变量、实例变量(私有变量和公有变量)、方法(包括静态方法staticmethod、类方法classmethod和实例方法instancemethod)。这里只着重介绍类的成员。

    通过语言描述会比较费事,下面通过例子来说明

    # coding: utf-8
    class MyClass:
        '''I simple example class'''
        val1 = 'Value 1'            #类变量
        val4 = 1
        def __init__(self):
            self.val2 = 'Value 2'   #公有实例变量
            self.__val3 = 'Value 3' #私有实例变量
    
        def __func():
            print 'val1 : ', MyClass.val1
            print 'static method cannot access val2'
            print 'static method cannot access __val3'
            print 'val4 : ', MyClass.val4
            MyClass.val4 = ((MyClass.val4 + 1))
    
        smd = staticmethod(__func)
    
        def __func2(cls):
            print 'val1 : ', cls.val1
            print 'class method cannot access val2'
            print 'class method cannot access __val3'
            print 'val4 : ', cls.val4
            cls.val4 = ((cls.val4 + 1))
    
        cmd = classmethod(__func2)
    
        def func3(self):
            print 'val1 : ', self.val1
            print 'val2 : ', self.val2
            print 'instance method cannot access __val3'
            print 'val4 : ', self.val4
            self.val4 = ((self.val4 + 1))

    这个类中已经基本包含了上面提到的类中的各种成员,然后通过调用看下这些成员有什么不同

    print '--------------------MyClass.smd()-------------------'
    MyClass.smd()        #类调用静态方法
    print '--------------------MyClass.cmd()-------------------'
    MyClass.cmd()        #类调用类方法
    #MyClass.func3()        #类无法直接调用实例方法
    
    x = MyClass()
    print '--------------------x.smd()-------------------'
    x.smd()            #实例调用静态方法
    print '--------------------x.cmd()-------------------'
    x.cmd()            #实例调用类方法
    print '--------------------x.func3()-------------------'
    x.func3()        #实例调用实例方法
    #结果
    --------------------MyClass.smd()-------------------
    val1 :  Value 1 
    static method cannot access val2
    static method cannot access __val3
    val4 :  1
    --------------------MyClass.cmd()-------------------
    val1 :  Value 1
    class method cannot access val2
    class method cannot access __val3
    val4 :  2
    --------------------x.smd()-------------------
    val1 :  Value 1
    static method cannot access val2
    static method cannot access __val3
    val4 :  3
    --------------------x.cmd()-------------------
    val1 :  Value 1
    class method cannot access val2
    class method cannot access __val3
    val4 :  4
    --------------------x.func3()-------------------
    val1 :  Value 1
    val2 :  Value 2
    instance method cannot access __val3
    val4 :  5

    结合上面的输出结果来解释下不同变量和方法的功能。

    静态方法,可以认为是一种全局方法,因为它不需要类实例化就能访问,和模块内的方法没什么区别,可以通过类和实例进行调用,它不能访问实例变量。当然,但能够通过类名访问类变量,如MyClass.val1。

    类方法,类似是个全局方法,它也能如静态方法那样被类调用,也能被实例调用,不同的是它通过实例来访问类变量,有类变量cls传入,并且有子类继承时,调用该类方法时,传入的类变量cls是子类,而非父类,如x.val1。

    实例方法,实例方法只能通过实例访问,它能够访问实例变量(公有)和类变量。

    私有方法,无法被类和实例调用。

    类变量,能够被类、类方法、实例和实例方法等访问。且在类和实例中进行传递(不停累加),如val4。

    实例变量(公有),能被实例和实例方法访问,但不能被类和类方法访问。

    实例变量(私有),不能被任何实例访问,但我们可以通过装饰器对其增加get/set方法来进行操作,具体在下面介绍。

    私有属性,通过在变量和方法前增加__(两个下划线)来定义。

    装饰器

    简单的说,装饰器就是对函数的一种装饰,可以在不修改被装饰函数定义和调用的情况下,增加对被调用函数的操作或指定其属性。 

    具体的介绍可以参看http://www.cnblogs.com/huxi/archive/2011/03/01/1967600.html

    语法糖

    通过装饰器简化方法装饰的代码

    # coding: utf-8 
    def deco(func):
        def _deco():
            print("before myfunc() called.")
            func()
            print("  after myfunc() called.")
        return _deco
     
    @deco
    def myfunc():
        print(" myfunc() called.")
        return 'ok'
     
    myfunc()
    myfunc()
    #输出
    before myfunc() called.
     myfunc() called.
      after myfunc() called.
    before myfunc() called.
     myfunc() called.
      after myfunc() called.

    多层装饰器

    @A
    @B
    @C
    def func():
    ...

    可以看成是A(B(C(func))),依次执行A、B、C和func。

    内置装饰器(将上面的MyClass类重新用装饰器定义一次,并增加对私有变量的操作方法)

    # coding: utf-8
    class MyClass:
        '''I simple example class'''
        val1 = 'Value 1'
        val4 = 1
        def __init__(self):
            self.val2 = 'Value 2'
            self.__val3 = 'Value 3'
    
        def func3(self):        #定义实例方法
            print 'val1 : ', self.val1
            print 'val2 : ', self.val2
            print 'instance method cannot access __val3'
            print 'val4 : ', self.val4
            self.val4 = ((self.val4 + 1))
    
        @classmethod            #定义类方法
        def func2(cls):
            print 'val1 : ', cls.val1
            print 'class method cannot access val2'
            print 'class method cannot access __val3'
            print 'val4 : ', cls.val4
            cls.val4 = ((cls.val4 + 1))
    
        @staticmethod            #定义静态方法
        def func():
            print 'val1 : ', MyClass.val1
            print 'static cannot access val2'
            print 'static method cannot access __val3'
            print 'val4 : ', MyClass.val4
            MyClass.val4 = ((MyClass.val4 + 1))
    
        @property            #私有实例变量get属性
        def val3(self):
            return self.__val3
    
        @val3.setter            #私有实例变量set属性
        def val3(self, value):
            self.__val3 = value
    
        @val3.deleter            #私有实例变量del属性
        def val3(self):
            del self.__val3

    @classmethod和@staticmethod分别代替了之前的类方法和静态方法的声明方式,除了简洁外没有其它特殊的意义。

    在2中定义的类中,有一个私有实例变量,它不能被类和实例所访问,我们通过增加@property和@setter来使实例能够对私有变量进行访问和赋值,并可以通过@deleter来将该变量删除。注意,类也能通过@property进行私有变量的访问,但无法通过@setter来给私有变量赋值,且@deleter不支持类访问。

    调用如下:

    print '-------------------MyClass.func()------------------'
    MyClass.func()
    
    
    x = MyClass()
    print '-------------------x.func()------------------'
    x.func()
    print '-------------------x.func2()------------------'
    x.func2()
    print '-------------------x.func3()------------------'
    x.func3()
    
    print ''
    print 'MyClass().val3 : ',MyClass().val3        #类调用property
    MyClass().val3 = 'New Value'            #类调用setter
    print 'after "MyClass().val3 = New Value" val3 :', MyClass().val3
    
    print''
    print 'val3 : ',x.val3                #实例调用property
    x.val3 = 'New Value'                #实例调用setter
    print 'after "x.val3 = New Value" val3 :', x.val3
    del x.val3                    #实例调用deleter
    print 'after "del x.val3"  val3 : ', x.val3
    #结果
    -------------------MyClass.func()------------------
    val1 :  Value 1
    static cannot access val2
    static method cannot access __val3
    val4 :  1
    -------------------x.func()------------------
    val1 :  Value 1
    static cannot access val2
    static method cannot access __val3
    val4 :  2
    -------------------x.func2()------------------
    val1 :  Value 1
    class method cannot access val2
    class method cannot access __val3
    val4 :  3
    -------------------x.func3()------------------
    val1 :  Value 1
    val2 :  Value 2
    instance method cannot access __val3
    val4 :  4
    
    MyClass().val3 :  Value 3                #类调用property
    after "MyClass().val3 = New Value" val3 : Value 3    #类调用setter没有生效
    
    val3 :  Value 3                    #实例调用property
    after "x.val3 = New Value" val3 : New Value    #实例调用setter
    after "del x.val3"  val3 :  Value 3        #实例调用deleter

    以上很多纯属个人理解,如有错误,还望指正

    上文有个例子摘自http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html

  • 相关阅读:
    SpringMVC返回JSON数据时日期格式化问题
    elementUI-tree组件 懒加载
    vue elementUi tree 懒加载使用详情
    Mybatis ResultMap Collection 复合主键
    ElasticSearch-IK分词
    Spring中的InitializingBean接口的使用
    ContextLoadListener & DispatcherServlet 加载顺序以及加载过程
    Spring中查看加载配置文件中 加载类的个数及详情
    DispatcherServlet 被加载顺序
    JetBrainsIDEA-structure结构继承的图标说明
  • 原文地址:https://www.cnblogs.com/geekma/p/2915623.html
Copyright © 2011-2022 走看看