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构建Hopfield网络的教程
Apr 14 Python
python爬虫入门教程--优雅的HTTP库requests(二)
May 25 Python
python开发准备工作之配置虚拟环境(非常重要)
Feb 11 Python
对python 通过ssh访问数据库的实例详解
Feb 19 Python
Ubuntu下Anaconda和Pycharm配置方法详解
Jun 14 Python
Python使用itchat模块实现群聊转发,自动回复功能示例
Aug 26 Python
python jenkins 打包构建代码的示例代码
Nov 29 Python
python多进程重复加载的解决方式
Dec 13 Python
Python requests模块session代码实例
Apr 14 Python
浅谈anaconda python 版本对应关系
Oct 07 Python
python实现b站直播自动发送弹幕功能
Feb 20 Python
再谈python_tkinter弹出对话框创建
Mar 20 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
PHP4引用文件语句的对比
2006/10/09 PHP
js 连接数据库如何操作数据库中的数据
2012/11/23 Javascript
JS动态添加option和删除option(附实例代码)
2013/04/01 Javascript
几种设置表单元素中文本输入框不可编辑的方法总结
2013/11/25 Javascript
js实现Select头像选择实时预览代码
2015/08/17 Javascript
详解JavaScript的回调函数
2015/11/20 Javascript
AngularJS进行性能调优的7个建议
2015/12/28 Javascript
AngularJS教程之MVC体系结构详解
2016/08/16 Javascript
jQuery EasyUI右键菜单实现关闭标签/选项卡
2016/10/10 Javascript
JS实现密码框的显示密码和隐藏密码功能示例
2016/12/26 Javascript
JavaScript Uploadify文件上传实例
2017/02/28 Javascript
JS+HTML实现的圆形可点击区域示例【3种方法】
2018/08/01 Javascript
详解Vue组件插槽的使用以及调用组件内的方法
2018/11/13 Javascript
详解vue-router导航守卫
2019/01/19 Javascript
解决layer弹出层中表单不起作用的问题
2019/09/09 Javascript
微信小程序实现音乐播放器
2019/11/20 Javascript
解决vue-photo-preview 异步图片放大失效的问题
2020/07/29 Javascript
在vue中使用image-webpack-loader实例
2020/11/12 Javascript
[02:33]2014DOTA2 TI每日综述 LGD涉险晋级DK闯入胜者组
2014/07/14 DOTA
python使用Flask框架获取用户IP地址的方法
2015/03/21 Python
Python3 适合初学者学习的银行账户登录系统实例
2017/08/08 Python
python实现可变变量名方法详解
2019/07/01 Python
详解Python利用random生成一个列表内的随机数
2019/08/21 Python
pyftplib中文乱码问题解决方案
2020/01/11 Python
python/golang实现循环链表的示例代码
2020/09/14 Python
python 数据类型强制转换的总结
2021/01/25 Python
Perfume’s Club澳大利亚官网:西班牙领先的在线美容店
2021/02/01 全球购物
犯错检讨书
2014/02/21 职场文书
大学生求职信例文
2014/06/29 职场文书
房地产经营管理专业自荐信
2014/09/02 职场文书
校园安全广播稿范文
2014/09/25 职场文书
化工见习报告范文
2014/10/31 职场文书
2014年酒店工作总结与计划
2014/11/17 职场文书
python中os.path.join()函数实例用法
2021/05/26 Python
MySQL利用UNION连接2个查询排序失效详解
2021/11/20 MySQL
PYTHON使用Matplotlib去实现各种条形图的绘制
2022/03/22 Python