python中的实例方法、静态方法、类方法、类变量和实例变量浅析


Posted in Python onApril 26, 2014

注:使用的是Python2.7。

一、实例方法

实例方法就是类的实例能够使用的方法。如下:

class Foo:
    def __init__(self, name):
        self.name = name
    def hi(self):
        print self.name
if __name__ == '__main__':
    foo01 = Foo('letian')
    foo01.hi()
    print type(Foo)
    print type(foo01)
    print id(foo01)
    print id(Foo)

运行结果为:
letian
<type 'classobj'>
<type 'instance'>
40124704
31323448[code]
可以看到,Foo的type为classobj(类对象,python中定义的类本身也是对象),foo01的type为instance(实例)。而hi()是实例方法,所以foo01.hi()会输出'letian'。实例方法的第一个参数默认为self,代指实例。self不是一个关键字,而是约定的写法。init()是生成实例时默认调用的实例方法。将Foo的定义改为以下形式:
[code]class Foo:
    def __init__(this, name):
        this.name = name
    def hi(here):
        print here.name

运行依然正确。 内置函数id用来查看对象的标识符,下面是其doc内容:
>>> print id.__doc__
id(object) -> integer
Return the identity of an object.  This is guaranteed to be unique among
simultaneously existing objects.  (Hint: it's the object's memory address.)

二、静态方法

静态方法是一种普通函数,就位于类定义的命名空间中,它不会对任何实例类型进行操作。使用装饰器@staticmethod定义静态方法。类对象和实例都可以调用静态方法:

class Foo:
    def __init__(self, name):
        self.name = name
    def hi(self):
        print self.name
    @staticmethod
    def add(a, b):
        print a + b
if __name__ == '__main__':
    foo01 = Foo('letian')
    foo01.hi()
    foo01.add(1,2)
    Foo.add(1, 2)

    运行结果如下:

letian
3
3

注意,很多编程语言不允许实例调用静态方法。

三、类方法

类方法是将类本身作为对象进行操作的方法。类方法使用@classmethod装饰器定义,其第一个参数是类,约定写为cls。类对象和实例都可以调用类方法:

class Foo:
    name = 'letian '
    @classmethod
    def hi(cls, x):
        print cls.name * x
if __name__ == '__main__':
    foo01 = Foo()
    foo01.hi(2)
    Foo.hi(3)

运行结果如下:
letian letian 
letian letian letian

注意,很多其他的编程语言不允许实例调用类方法。

四、super

super用来执行父类中的函数,例如:

class Foo(object):
    def hi(self):
        print 'hi,Foo'
class Foo2(Foo):
    def hi(self):
        super(Foo2, self).hi()
if __name__ == '__main__':
    foo2 = Foo2()
    foo2.hi()

运行结果:
hi,Foo

注意,Foo类必须继承某个类(并且这个继承链开始于object类),否则会报错。如果改成下面的形式:
class Foo:
    def hi(self):
        print 'hi,Foo'
class Foo2(Foo):
    def hi(self):
        super(Foo2, self).hi()
if __name__ == '__main__':
    foo2 = Foo2()
    foo2.hi()

运行时报错如下:
......
TypeError: must be type, not classobj

关于super,具体请见http://docs.python.org/2/library/functions.html?highlight=super#super以及super.doc。

五、类变量和实例变量

类变量定义在类的定义之后,实例变量则是以为self.开头。例如:

class Foo(object):
    val = 0
    def __init__(self):
        self.val = 1
if __name__ == '__main__':
    foo = Foo()
    print foo.val
    print Foo.val

运行结果为:
1
0

实例也能够访问类变量,如下:
class Foo(object):
    val = 0
    def __init__(self):
        pass
if __name__ == '__main__':
    foo = Foo()
    print foo.val
    print Foo.val

运行结果如下:
0
0

另外,可以通过以下方式访问类变量:
class Foo(object):
    val = 3
    def __init__(self):
        print self.__class__.val
if __name__ == '__main__':
    foo = Foo()

运行结果:
3

还可以这样:
class Foo(object):
    val = 3
    def __init__(self):
        pass
    @classmethod
    def echo(cls):
        print cls.val
if __name__ == '__main__':
    Foo.echo()

运行结果:
3

六、如何调用父类的构造函数

子类(派生类)并不会自动调用父类(基类)的init方法,例如:

class Foo(object):
    def __init__(self):
        self.val = 1
class Foo2(Foo):
    def __init__(self):
        print self.val
if __name__ == '__main__':
    foo2 = Foo2()

运行时报错。

调用父类的init方法有两种,第一种:

class Foo(object):
    def __init__(self):
        self.val = 1
class Foo2(Foo):
    def __init__(self):
        Foo.__init__(self)
        print self.val
if __name__ == '__main__':
    foo2 = Foo2()

第二种:
class Foo(object):
    def __init__(self):
        self.val = 1
class Foo2(Foo):
    def __init__(self):
        super(Foo2,self).__init__()
        print self.val
if __name__ == '__main__':
    foo2 = Foo2()

这两种方法的运行结果均为:
1

不过这两种方法是有区别的。
Python 相关文章推荐
使用Python来开发Markdown脚本扩展的实例分享
Mar 04 Python
python 自动化将markdown文件转成html文件的方法
Sep 23 Python
python多进程和多线程究竟谁更快(详解)
May 29 Python
Zookeeper接口kazoo实例解析
Jan 22 Python
Python找出微信上删除你好友的人脚本写法
Nov 01 Python
pandas通过loc生成新的列方法
Nov 28 Python
python如何实现代码检查
Jun 28 Python
python交易记录整合交易类详解
Jul 03 Python
Django 实现图片上传和显示过程详解
Jul 18 Python
python @classmethod 的使用场合详解
Aug 23 Python
详解Python 函数参数的拆解
Sep 02 Python
Python四款GUI图形界面库介绍
Jun 05 Python
Python设计模式之单例模式实例
Apr 26 #Python
Python设计模式之观察者模式实例
Apr 26 #Python
Python设计模式之代理模式实例
Apr 26 #Python
python中的列表推导浅析
Apr 26 #Python
Python中的Numpy入门教程
Apr 26 #Python
Python中的map、reduce和filter浅析
Apr 26 #Python
Python实现的Kmeans++算法实例
Apr 26 #Python
You might like
LotusPhp笔记之:Cookie组件的使用详解
2013/05/06 PHP
浅析51个PHP处理字符串的函数
2013/08/02 PHP
php求两个目录的相对路径示例(php获取相对路径)
2014/03/27 PHP
javascript中的location用法简单介绍
2007/03/07 Javascript
JQuery 实现的页面滚动时浮动窗口控件
2009/07/10 Javascript
JS的数组迭代方法
2015/02/05 Javascript
javascript与css3动画结合使用小结
2015/03/11 Javascript
js实现跨域的多种方法
2015/12/25 Javascript
详解Angular的内置过滤器和自定义过滤器【推荐】
2016/12/26 Javascript
详解angular element()方法使用
2017/04/08 Javascript
Vue+axios 实现http拦截及路由拦截实例
2017/04/25 Javascript
详解angular 中的自定义指令之详解API
2017/06/20 Javascript
bootstrap table实现x-editable的行单元格编辑及解决数据Empty和支持多样式问题
2017/08/10 Javascript
使用cookie绕过验证码登录的实现代码
2017/10/12 Javascript
JS简单实现数组去重的方法分析
2017/10/14 Javascript
vue 中动态绑定class 和 style的方法代码详解
2018/06/01 Javascript
Node.js log4js日志管理详解
2018/07/31 Javascript
vue配置font-awesome5的方法步骤
2019/01/27 Javascript
详解mpvue中小程序自定义导航组件开发指南
2019/02/11 Javascript
基于vue实现滚动条滚动到指定位置对应位置数字进行tween特效
2019/04/18 Javascript
深入浅出 Vue 系列 -- 数据劫持实现原理
2019/04/23 Javascript
超简单的微信小程序轮播图
2019/11/22 Javascript
微信小程序保存图片到相册权限设置
2020/04/09 Javascript
ant-design-vue按需加载的坑的解决
2020/05/14 Javascript
jQuery加PHP实现图片上传并提交的示例代码
2020/07/16 jQuery
[00:52]玛尔斯技能全介绍
2019/03/06 DOTA
Python的Flask站点中集成xhEditor文本编辑器的教程
2016/06/13 Python
用 Python 连接 MySQL 的几种方式详解
2018/04/04 Python
python字典改变value值方法总结
2019/06/21 Python
pytorch方法测试——激活函数(ReLU)详解
2020/01/15 Python
python实现PDF中表格转化为Excel的方法
2020/06/16 Python
Python读写锁实现实现代码解析
2020/11/28 Python
不假外出检讨书
2014/01/27 职场文书
2015年财务工作总结范文
2015/03/31 职场文书
2015年工商局个人工作总结
2015/07/23 职场文书
Nginx URL重写rewrite机制原理及使用实例
2021/04/01 Servers