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的迭代器与生成器实例详解
Jul 16 Python
Pyhthon中使用compileall模块编译源文件为pyc文件
Apr 28 Python
python脚本监控docker容器
Apr 27 Python
Python判断字符串是否为字母或者数字(浮点数)的多种方法
Aug 03 Python
python django 原生sql 获取数据的例子
Aug 14 Python
Python字符串和正则表达式中的反斜杠('\')问题详解
Sep 03 Python
Python关于反射的实例代码分享
Feb 20 Python
iPython pylab模式启动方式
Apr 24 Python
pytorch快速搭建神经网络_Sequential操作
Jun 17 Python
django rest framework使用django-filter用法
Jul 15 Python
Java Unsafe类实现原理及测试代码
Sep 15 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 MessagePack介绍
2013/10/06 PHP
摘自织梦CMS的HTTP文件下载类
2015/08/08 PHP
thinkPHP中钩子的两种配置调用方法详解
2016/11/11 PHP
JS解密入门 最终变量劫持
2008/06/25 Javascript
jquery用get实现ajax在ie里面刷新不进入后台解决方法
2013/08/12 Javascript
函数window.open实现关闭所有的子窗口
2015/08/03 Javascript
js实现Select列表各项上移和下移的方法
2015/08/14 Javascript
js正则表达式验证邮件地址
2015/11/12 Javascript
JavaScript通过HTML的class来获取HTML元素的方法总结
2016/05/24 Javascript
jQuery过滤选择器经典应用
2016/08/18 Javascript
AngularJS获取json数据的方法详解
2017/05/27 Javascript
Vue配置marked链接添加target=&quot;_blank&quot;的方法
2019/07/19 Javascript
茶余饭后聊聊Vue3.0响应式数据那些事儿
2019/10/30 Javascript
js 获取本周、上周、本月、上月、本季度、上季度的开始结束日期
2020/02/01 Javascript
基于JavaScript实现简单抽奖功能代码实例
2020/10/20 Javascript
[01:37]TI4西雅图DOTA2前线报道 VG拿下首胜教练357给出获胜秘诀
2014/07/10 DOTA
python处理图片之PIL模块简单使用方法
2015/05/11 Python
关于Python面向对象编程的知识点总结
2017/02/14 Python
使用Anaconda3建立虚拟独立的python2.7环境方法
2018/06/11 Python
Python3+OpenCV2实现图像的几何变换(平移、镜像、缩放、旋转、仿射)
2019/05/13 Python
Python csv模块使用方法代码实例
2019/08/29 Python
Python 安装 virturalenv 虚拟环境的教程详解
2020/02/21 Python
Python爬虫之Selenium多窗口切换的实现
2020/12/04 Python
PyCharm+Miniconda3安装配置教程详解
2021/02/16 Python
PHP中如何创建和修改数组
2012/05/02 面试题
国际金融专业大学生职业生涯规划书
2013/12/28 职场文书
大学毕业后的十年规划
2014/01/07 职场文书
市级文明单位申报材料
2014/05/07 职场文书
初中毕业典礼演讲稿
2014/09/09 职场文书
出售房屋协议书范本
2014/10/06 职场文书
2014年干部作风建设总结
2014/10/23 职场文书
就业意向协议书
2015/01/29 职场文书
nginx配置文件使用环境变量的操作方法
2021/06/02 Servers
Mysql数据库表中为什么有索引却没有提高查询速度
2022/02/24 MySQL
关于python3 opencv 图像二值化的问题(cv2.adaptiveThreshold函数)
2022/04/04 Python
MySQL优化之慢日志查询
2022/06/10 MySQL