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 mysqldb连接数据库
Mar 16 Python
Python 爬虫的工具列表大全
Jan 31 Python
Python Socket编程详细介绍
Mar 23 Python
Django数据库操作的实例(增删改查)
Sep 04 Python
python简单实例训练(21~30)
Nov 15 Python
Python可变参数*args和**kwargs用法实例小结
Apr 27 Python
matplotlib savefig 保存图片大小的实例
May 24 Python
Python实现栈和队列的简单操作方法示例
Nov 29 Python
彻底搞懂 python 中文乱码问题(深入分析)
Feb 28 Python
python实现将中文日期转换为数字日期
Jul 14 Python
python基础之错误和异常处理
Oct 24 Python
梳理总结Python开发中需要摒弃的18个坏习惯
Jan 22 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
php函数之子字符串替换&amp;#65279; str_replace
2011/03/23 PHP
php中用date函数获取当前时间有误的解决办法
2013/08/02 PHP
jQuery 使用个人心得
2009/02/26 Javascript
JavaScript 打地鼠游戏代码说明
2010/10/12 Javascript
浅谈javascript的原型继承
2012/07/25 Javascript
JS画5角星方法介绍
2013/09/17 Javascript
jQuery实现HTML5 placeholder效果实例
2014/12/09 Javascript
用nodejs的实现原理和搭建服务器(动态)
2016/08/10 NodeJs
Angularjs 制作购物车功能实例代码
2016/09/14 Javascript
深入理解bootstrap框架之入门准备
2016/10/09 Javascript
炫酷的js手风琴效果
2016/10/13 Javascript
微信小程序自定义组件
2017/08/16 Javascript
echarts学习笔记之图表自适应问题详解
2017/11/22 Javascript
layer父页获取弹出层输入框里面的值方法
2019/09/02 Javascript
Vue 中使用lodash对事件进行防抖和节流操作
2020/07/26 Javascript
elementui更改el-dialog关闭按钮的图标d的示例代码
2020/08/04 Javascript
[00:36]我的中国心——Serenity vs Fnatic
2018/08/21 DOTA
用map函数来完成Python并行任务的简单示例
2015/04/02 Python
Python实现简单截取中文字符串的方法
2015/06/15 Python
python web框架学习笔记
2016/05/03 Python
Python操作Access数据库基本步骤分析
2016/09/19 Python
matplotlib绘制符合论文要求的图片实例(必看篇)
2017/06/02 Python
记一次django内存异常排查及解决方法
2020/08/07 Python
Python Charles抓包配置实现流程图解
2020/09/29 Python
python 生成器需注意的小问题
2020/09/29 Python
详解Anaconda安装tensorflow报错问题解决方法
2020/11/01 Python
微软澳洲官方网站:Microsoft Australia
2017/01/10 全球购物
怎样声明一个匿名的内部类
2016/06/01 面试题
职员竞岗演讲稿
2014/05/14 职场文书
春季运动会加油词
2015/07/18 职场文书
2016小学新学期寄语
2015/12/04 职场文书
2016党员干部反腐倡廉心得体会
2016/01/13 职场文书
《金色的草地》教学反思
2016/02/17 职场文书
iPhone13将有八大升级
2021/04/15 数码科技
nginx共享内存的机制详解
2022/03/21 Servers
多线程Spring通过@Scheduled实现定时任务
2022/05/25 Java/Android