zoukankan      html  css  js  c++  java
  • python小记(5)

    静态方法和类方法

    先看下面的代码

    #!/usr/bin/env python
    #coding:utf-8
    
    class Foo(object):        #Python 3: class Foo:
        one = 0
    
        def __init__(self):
            Foo.one = Foo.one + 1
    
    def get_class_attr(cls):
        return cls.one
    
    if __name__ == "__main__":
        f1 = Foo()
        print "f1:",Foo.one        #Python 3: print("f1:"+str(Foo.one)),下同,从略
        f2 = Foo()
        print "f2:",Foo.one
    
        print get_class_attr(Foo)
    

    在上述代码中,有一个函数get_class_attr(),这个函数的参数我用cls,从函数体的代码中看,要求它引用的对象应该具有属性one,这就说明,不是随便一个对象就可以的。恰好,就是这么巧,我在前面定义的类Foo中,就有one这个属性。于是乎,我在调用这个函数的时候,就直接将该类对象传给了它get_class_attr(Foo)

    其运行结果如下:

    f1: 1
    f2: 2
    2
    

    在这个程序中,函数get_class_attr()写在了类的外面,但事实上,函数只能调用前面写的那个类对象,因为不是所有对象都有那个特别的属性的。所以,这种写法,使得类和函数的耦合性太强了,不便于以后维护。这种写法是应该避免的。避免的方法就是把函数与类融为一体。于是就有了下面的写法。

    #!/usr/bin/env python
    #coding:utf-8
    
    class Foo(object):    #Python 3: class Foo:
        one = 0
    
        def __init__(self):
            Foo.one = Foo.one + 1
    
        @classmethod
        def get_class_attr(cls):
            return cls.one
    
    if __name__ == "__main__":
        f1 = Foo()
        print "f1:",Foo.one
        f2 = Foo()
        print "f2:",Foo.one
    
        print f1.get_class_attr()
        print "f1.one",f1.one
        print Foo.get_class_attr()
    
        print "*"* 10
        f1.one = 8
        Foo.one = 9
        print f1.one
        print f1.get_class_attr()
        print Foo.get_class_attr()
    

    在这个程序中,出现了@classmethod——装饰器——在函数那部分遇到过了。需要注意的是@classmethod所装饰的方法的参数中,第一个参数不是self,这是和我们以前看到的类中的方法是有区别的。这里我使用了参数cls,你用别的也可以,只不过习惯用cls

    再看对类的使用过程。先贴出上述程序的执行结果:

    f1: 1
    f2: 2
    2
    f1.one 2
    2
    **********
    8
    9
    9
    

    分别建立两个实例,此后类属性Foo.one的值是2,然后分别通过实例和类来调用get_class_attr()方法(没有显示写cls参数),结果都相同。

    当修改类属性和实例属性,再次通过实例和类调用get_class_attr()方法,得到的依然是类属性的结果。这说明,装饰器@classmethod所装饰的方法,其参数cls引用的对象是类对象Foo

    至此,可以下一个定义了。

    所谓类方法,就是在类里面定义的方法,该方法由装饰器@classmethod所装饰,其第一个参数cls所引用的是这个类对象,即将类本身作为引用对象传入到此方法中。

    理解了类方法之后,用同样的套路理解另外一个方法——静态方法。还是先看代码——一个有待优化的代码。

    #!/usr/bin/env python
    #coding:utf-8
    
    T = 1
    
    def check_t():
        T = 3
        return T 
    
    class Foo(object):        #Python 3: class Foo:
        def __init__(self,name):
            self.name = name
    
        def get_name(self):
            if check_t():
                return self.name
            else:
                return "no person"
    
    if __name__ == "__main__":
        f = Foo("canglaoshi")
        name = f.get_name()
        print name        #Python 3: print(name)
    

    先观察上面的程序,发现在类Foo里面使用了外面定义的函数check_t()。这种类和函数的关系,也是由于有密切关系,从而导致程序维护有困难,于是在和前面同样的理由之下,就出现了下面比较便于维护的程序。

    #!/usr/bin/env python
    #coding:utf-8
    
    T = 1
    
    class Foo(object):        #Python 3: class Foo:
        def __init__(self,name):
            self.name = name
    
        @staticmethod
        def check_t():
            T = 1
            return T
    
        def get_name(self):
            if self.check_t():       
                return self.name
            else:
                return "no person"
    
    if __name__ == "__main__":
        f = Foo("canglaoshi")
        name = f.get_name()
        print name        #Python 3: print(name)
    

    经过优化,将原来放在类外面的函数,移动到了类里面,也就是函数check_t()现在位于类Foo的命名空间之内了。但是,不是简单的移动,还要在这个函数的前面加上@staticmethod装饰器,并且要注意的是,虽然这个函数位于类的里面,跟其它的方法不同,它不以self为第一个参数。当使用它的时候,可以通过实例调用,比如self.check_t();也可以通过类调用这个方法,比如Foo.check_t()

    从上面的程序可以看出,尽管check_t()位于类的命名空间之内,它却是一个独立的方法,跟类没有什么关系,仅仅是为了免除前面所说的维护上的困难,写在类的作用域内的普通函数罢了。但,它的存在也是有道理的,以上的例子就是典型说明。当然,在类的作用域里面的时候,前面必须要加上一个装饰器@staticmethod。我们将这种方法也给予命名,称之为静态方法。

    方法,是类的重要组成部分。本节专门讲述了方法中的几种特殊方法,它们为我们使用类的方法提供了更多便利的工具。但是,类的重要特征之一——继承,还没有亮相。

  • 相关阅读:
    Flask11 Session、CSRF、注销session、利用端点自动跳转
    python学习笔记4-时间函数
    python学习笔记3-循环1
    python学习笔记2-条件语句
    python学习笔记1-基础语法
    sprintf系列函数
    sscanf非常的重要
    c++中.c_str和.c_data
    c++Map用法
    c语言sscanf总结
  • 原文地址:https://www.cnblogs.com/liqiantu/p/5791529.html
Copyright © 2011-2022 走看看