正文
与其他编程语言相比,Python的类机制以最少的新语法和语义添加类。Python类提供了面向对象编程的所有标准功能:类继承机制允许多个基类,派生类可以重写其基类或类的任何方法,而方法可以调用具有相同名称的基类的方法。对象可以包含任意数量和种类的数据,和模块一样,类也是Python的动态特性的一部分,它们是在运行时创建的,可以在创建后进一步修改。
本文旨在通过介绍Python面向对象编程中的类方法、静态方法,提高大家对Python面向对象编程基础知识的认识。
1
名词解释
静态方法,用作类似一个单纯的函数,需要通过类去调用,不能独立存在。需要使用类有关系的功能但在运行时又不需要实例和类参与的情况下需要用到静态方法。
一些仅仅与类交互而不是和实例交互的方法,只能访问类变量,不能访问实例变量。
2
通过代码举例普通方法
<code class="hljs language-python" style="font-size: 0.85em;font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em;white-space: pre;overflow: auto;border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);padding: 0.5em;color: rgb(51, 51, 51);background: rgb(248, 248, 248);text-size-adjust: none;display: block !important;">class Kls(object):
def __init__(self, data):
self.data = data
def printd(self):
print(self.data)
ik1 = Kls('arun')
ik2 = Kls('seema')
ik1.printd()
ik2.printd()
#执行结果
#输出
arun
seema
然后看一下代码和示例图片:
如果现在我们想写一些仅仅与类交互而不是和实例交互的方法会怎么样呢?我们可以在类外面写一个简单的方法来做这些,但是这样做就扩散了类代码的关系到类定义的外面。如果像下面这样写就会导致以后代码维护的困难:
def get_no_of_instances(cls_obj):
return cls_obj.no_inst
class Kls(object):
no_inst = 0
def __init__(self):
Kls.no_inst = Kls.no_inst + 1
ik1 = Kls()
ik2 = Kls()
print(get_no_of_instances(Kls))
#执行结果
#输出:
2
这该怎么办呢?不急,下面我们慢慢谈到。
3
类方法
上面我们提到了存在一些仅仅与类交互而不是和实例交互的情况,可以通过在类外面写一个简单的方法来做这些,但是这样做就扩散了类代码的关系到类定义的外面。再举一个类似的例子:
def iget_no_of_instance(ins_obj):
return ins_obj.__class__.no_inst
class Kls(object):
no_inst = 0
def __init__(self):
Kls.no_inst = Kls.no_inst + 1
ik1 = Kls()
ik2 = Kls()
print(iget_no_of_instance(ik1))
#执行结果
#输出:
2
这种写法是不符合面向对象编程的基本原则的,Python中为我们提供了@classmethod方法来解决,通过这种方法描述一个类方法,例如:
class Kls(object):
no_inst = 0
def __init__(self):
Kls.no_inst = Kls.no_inst + 1
@classmethod
def get_no_of_instance(cls_obj):
return cls_obj.no_inst
ik1 = Kls()
ik2 = Kls()
print ik1.get_no_of_instance()
print Kls.get_no_of_instance()
#执行结果
#输出
2
2
这样的好处是: 不管这个方式是从实例调用还是从类调用,它都用第一个参数把类传递过来。大家仔细看没有,类方法可以直接用类名调用哦!
print Kls.get_no_of_instance()
需要注意的是:类方法python静态方法,只能访问类变量,不能访问实例变量。
class Kls(object):
no_inst = 0
def __init__(self,data):
Kls.no_inst = Kls.no_inst + 1
self.data = data
@classmethod
def get_no_of_instance(cls_obj):
return self.data
ik1 = Kls('apple')
print ik1.get_no_of_instance()
#执行结果
Traceback (most recent call last):
File "C:UsersAdministratorDesktopnew 1.py", line 35, in
print ik1.get_no_of_instance()
File "C:UsersAdministratorDesktopnew 1.py", line 32, in get_no_of_instance
return self.data
NameError: global name 'self' is not defined
4
静态方法
经常有一些跟类有关系的功能但在运行时又不需要实例和类参与的情况下需要用到静态方法。比如更改环境变量或者修改其他类的属性等能用到静态方法。这种情况可以直接用函数解决python静态方法,但这样同样会扩散类内部的代码,造成维护困难。比如这样:
IND = 'ON'
def checkind():
return (IND == 'ON')
class Kls(object):
def __init__(self,data):
self.data = data
def do_reset(self):
if checkind():
print('Reset done for:', self.data)
def set_db(self):
if checkind():
self.db = 'new db connection'
print('DB connection made for:',self.data)
ik1 = Kls(12)
ik1.do_reset()
ik1.set_db()
#执行结果
#输出:
Reset done for: 12
DB connection made for: 12
如果使用@staticmethod就能把相关的代码放到对应的位置了。
IND = 'ON'
class Kls(object):
def __init__(self, data):
self.data = data
@staticmethod
def checkind():
print('ok')
return (IND == 'ON')
def do_reset(self):
if self.checkind():
print('Reset done for:', self.data)
def set_db(self):
if self.checkind():
self.db = 'New db connection'
print('DB connection made for: ', self.data)
ik1 = Kls(12)
ik1.do_reset()
ik1.set_db()
Kls.checkind()
#执行结果
#输出:
ok
('Reset done for:', 12)
ok
('DB connection made for: ', 12)
ok
与类方法类似,静态方法也可以直接用类名调用哦!
这里也需要注意的是:静态方法里无法访问实例中的任何属性。
class Kls(object):
def __init__(self, data):
self.data = data
@staticmethod
def checkind():
return (IND == self.data)
def do_reset(self):
if self.checkind():
print('Reset done for:', self.data)
def set_db(self):
if self.checkind():
self.db = 'New db connection'
print('DB connection made for: ', self.data)
ik1 = Kls(12)
ik1.do_reset()
ik1.set_db()
#执行结果
Traceback (most recent call last):
File "C:UsersAdministratorDesktopnew 1.py", line 43, in
ik1.do_reset()
File "C:UsersAdministratorDesktopnew 1.py", line 34, in do_reset
if self.checkind():
File "C:UsersAdministratorDesktopnew 1.py", line 31, in checkind
return (IND == self.data)
NameError: global name 'self' is not defined
5
总结
下面这个更全面的代码和图示来展示@staticmethod和@classmethod的不同
class Kls(object):
def __init__(self, data):
self.data = data
def printd(self):
print(self.data)
@staticmethod
def smethod(*arg):
print('Static:', arg)
@classmethod
def cmethod(*arg):
print('Class:', arg)
>>> ik = Kls(23)
>>> ik.printd()
23
>>> ik.smethod()
Static: ()
>>> ik.cmethod()
Class: (,)
>>> Kls.printd()
TypeError: unbound method printd() must be called with Kls instance as first argument (got nothing instead)
>>> Kls.smethod()
Static: ()
>>> Kls.cmethod()
Class: (,)
看完本文有收获?请转发分享给更多人
限时特惠:本站每日持续更新海量设计资源,一年会员只需29.9元,全站资源免费下载
站长微信:ziyuanshu688