24.静态方法和类方法
静态方法和类方法
静态方法和类方法在 Python2.2 中引入。经典类及新式(new-style)类中都可以使用它
通常的方法需要一个实例(self)作为第一个参数,并且对于(绑定的)方法调用来说,self
是自动传递给这个方法的。而对于类方法而言,需要类而不是实例作为第一个参数,它是由解释器传给方法。类不需要特别地命名, 类似
self,不过很多人使用 cls 作为变量名字
静态方法和类方法结合例子: 早期没有引入函数装饰符时
class TestStaticMethod:
def foo():
print 'calling static method foo()'
foo = staticmethod(foo) #将方法转换为静态方法
class TestClassMethod:
def foo(cls):
print 'calling class method foo()'
print 'foo() is part of class:', cls.__name__
foo = classmethod(foo) #
将方法转换为类方法
执行:
>>> tsm = TestStaticMethod()
>>> TestStaticMethod.foo() #
通过类对象本身调用静态方法
calling static method foo()
>>> tsm.foo() #
通过实例对象调用静态方法
calling static method foo()
>>>
>>> tcm = TestClassMethod()
>>> TestClassMethod.foo() #
通过类对象本身调用类方法
calling class method foo()
foo() is part of class: TestClassMethod
>>> tcm.foo() #
通过实例对象调用类方法
calling class method foo()
foo() is part of class: TestClassMethod
注意:如果执行在文件中用print打印则会出现如下结果:
#!/usr/bin/env python
#coding:utf8
class TestStaticMethod:
def foo():
print 'calling static method foo()'
foo = staticmethod(foo) #将方法转换为静态方法
class TestClassMethod:
def foo(cls):
print 'calling class method foo()'
print 'foo() is part of class:', cls.__name__
foo = classmethod(foo) # 将方法转换为类方法
tsm = TestStaticMethod()
print TestStaticMethod.foo() #通过类对象本身调用静态方法
print tsm.foo() # 通过实例对象调用静态方法
tcm = TestClassMethod()
print TestClassMethod.foo() #通过类对象本身调用类方法
print tcm.foo() # 通过实例对象调用类方法
执行结果:
calling static method foo()
None
calling static method foo()
None
calling class method foo()
foo() is part of class: TestClassMethod
None
calling class method foo()
foo() is part of class: TestClassMethod
None
因为在python函数中,如果没有return语句,会自动返回NONE,如果有return语句,但是return后面没有接表达式或者值的话也是返回NONE
优化代码:
#!/usr/bin/env python
#coding:utf8
class TestStaticMethod:
def foo():
return 'calling static method foo()'
foo = staticmethod(foo) #将方法转换为静态方法
class TestClassMethod:
def foo(cls):
print 'calling class method foo()'
return 'foo() is part of class:', cls.__name__
foo = classmethod(foo) # 将方法转换为类方法
tsm = TestStaticMethod()
print TestStaticMethod.foo() #通过类对象本身调用静态方法
print tsm.foo() # 通过实例对象调用静态方法
tcm = TestClassMethod()
print TestClassMethod.foo() #通过类对象本身调用类方法
print tcm.foo() # 通过实例对象调用类方法
执行结果:
calling static method foo()
calling static method foo()
calling class method foo()
('foo() is part of class:', 'TestClassMethod')
calling class method foo()
('foo() is part of class:', 'TestClassMethod')
使用函数修饰符
1、函数修饰符,一种在 Python2.4 中加入的新特征
2、你可以用它把一个函数应用到另个函数对象上, 而且新函数对象依然绑定在原来的变量。
3、我们正是需要它来整理语法。通过使用 decorators,我们可以避免像上面那样的重新赋值
#!/usr/bin/env python
#coding:utf8
class TestStaticMethod:
@staticmethod
def foo():
print 'calling static method foo()'
class TestClassMethod:
@classmethod
def foo(cls):
print 'calling class method foo()'
print 'foo() is part of class:', cls.__name__
tsm = TestStaticMethod()
TestStaticMethod.foo() #通过类对象本身调用静态方法
tsm.foo() # 通过实例对象调用静态方法
tcm = TestClassMethod()
TestClassMethod.foo() #通过类对象本身调用类方法
tcm.foo() # 通过实例对象调用类方法
执行结果:
calling static method foo()
calling static method foo()
calling class method foo()
foo() is part of class: TestClassMethod
calling class method foo()
foo() is part of class: TestClassMethod
类方法
1、由类调用
2、第一个参数必须是类对象,一般以cls作为第一个参数
3、能够通过实例对象和类对象去访问
#!/usr/bin/env pythn
#coding:utf-8
class People(object):
country = 'china'
#类方法,用classmethod来进行修饰
@classmethod
def getCountry(cls):
return cls.country
p = People()
print p.getCountry() #可以用过实例对象引用
print People.getCountry() #可以通过类对象引用
执行结果:
china
china
类方法还有一个用途就是可以对类属性进行修改:
#!/usr/bin/env python
#coding:utf-8
class People(object):
country = 'china'
#类方法,用classmethod来进行修饰
@classmethod
def getCountry(cls):
return cls.country
@classmethod
def setCountry(cls,country):
cls.country = country
p = People()
print p.getCountry() #可以用过实例对象引用
print People.getCountry() #可以通过类对象引用
p.setCountry('janpan')
print p.getCountry()
print People.getCountry()
执行结果:
china
china
janpan
janpan
静态方法
需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数
#!/usr/bin/env python
#coding:utf-8
class People(object):
country = 'china'
@staticmethod
#静态方法
def getCountry():
return People.country
print People.getCountry()
执行结果:
china
总结
1、从类方法和实例方法以及静态方法的定义形式就可以看出来,类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法;
2、实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。
3、静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类对象来引用
下面看一下例子:
#!/usr/bin/env python #coding:utf8 class Foo(object): '''类三种方法语法形式''' # 在类中定义普通方法,在定义普通方法的时候,必须添加self def instance_method(self): print "是类{}的实例方法,只能被实例对象调用".format(Foo) # 在类中定义静态方法,在定义静态方法的时候,不需要传递任何类的东西 @staticmethod def static_method(): print("是静态方法") # 在类中定义类方法,在定义类方法的时候,需要传递参数cls cls即为类本身 @classmethod def class_method(cls): print("是类方法") foo = Foo() foo.instance_method() foo.class_method() foo.static_method() print "---------------" Foo.static_method() Foo.class_method()
可以看出:
1.实例方法只能被实例对象调用;静态方法(由@staticmethod装饰的方法)、类方法(由@classmethod装饰的方法),可以被类或类的实例对象调用。
实例方法,第一个参数必须要默认传实例对象,一般习惯用self。对象方法中有self参数,类方法有cls参数,静态方法是不需要这些附加参数
2.静态方法(@staticmethod):即静态方法,静态方法是一类特殊的方法,有时候你可能需要填写一个属于这个类的方法,但是这些代码完全不会使用到实例对象本身。
当一个函数逻辑上属于一个类又不依赖与类的属性的时候,可以使用staticmethod。
使用staticmethod可以避免每次使用的时都会创建一个对象的开销。
staticmethod可以使用类和类的实例调用。但是不依赖于类和类的实例的状态。
3.类方法(@classmethod):即类方法,类方法不是绑定到对象上,而是绑定在类上的方法,它更关注于从类中调用方法,而不是从实例中调用方法,如构造重载;
classmethod是类对象与函数的结合。
可以使用类和类的实例调用,但是都是将类作为隐含参数传递过去。
使用类来调用classmethod可以避免将类实例化的开销
4.成员函数:实例的方法,只能通过实例进行调用;
类方法与静态方法说明
1:self表示为类型为类的object,而cls表示为类也就是class
2:在定义普通方法的时候,需要的是参数self,也就是把类的实例作为参数传递给方法,如果不写self的时候,会发现报错TypeError错误,表示传递的参数多了,
其实也就是调用方法的时候,将实例作为参数传递了,在使用普通方法的时候,使用的是实例来调用方法,不能使用类来调用方法,没有实例,那么方法将无法调用。
3:在定义静态方法的时候,和模块中的方法没有什么不同,最大的不同就是在于静态方法在类的命名空间之间,而且在声明静态方法的时候,
使用的标记为@staticmethod,表示为静态方法,在你用静态方法的时候,可以使用类名或者是实例名来进行调用,一般使用类名来调用
4:静态方法主要是用来放一些方法的,方法的逻辑属于类,但是有何类本身没有什么交互,从而形成了静态方法,主要是让静态方法放在此类的名称空间之内,
从而能够更加有组织性。
5:在定义类方法的时候,传递的参数为cls.表示为类,此写法也可以变,但是一般写为cls。类的方法调用可以使用类,也可以使用实例,一般情况使用的是类。
6:在重载调用父类方法的时候,最好是使用super来进行调用父类的方法。静态方法主要用来存放逻辑性的代码,基本在静态方法中,不会涉及到类的方法和类的参数。
类方法是在传递参数的时候,传递的是类的参数,参数是必须在cls中进行隐身穿
7:python中实现静态方法和类方法都是依赖python的修饰器来实现的。静态方法是staticmethod,类方法是classmethod。