类中的方法,其实就是类中的函数,可以分为:实例方法,类方法,静态方法。方法和字段一样,也是属于类的属性,所以也具有运行中修改的特效, 但一般不推荐这样做。
我在类的基本语法中,介绍了构造器方法:__init__ 、__new__;解构器方法:__del__;
注意,这里虽然是以两个下划线(__)开头,但同时以两个下划线(__)结尾,这里表明其是一个‘魔法方法’,关于类中的魔法方法,将起一篇进行说明。
但是,如果单纯只以两个下划线开始,则依然是私有化的意思,看代码示例:
class Test(object):
def __scolia__(self): # 一个类似魔术方法,并不是私有化
return 'scolia'
def __good(self): # 私有方法
return 'good'
a = Test()
print a.__scolia__() # 魔法方法可以在直接访问
print a.__good() # 私有方法不能直接访问
同样的,和字段私有化一样,我们也可能同特殊手段进行强制访问:
print a._Test__good() # 强制访问
当然,私有方法也可以在类的内部访问,和私有字段一样。
所以说,属性的私有化都是对访问入口进行混淆,同样的,也不建议强制访问私有属性。
也许这里的‘魔法方法’看起来并不‘魔法’,详情将以后解释。
实例方法:
在 __init__ 构造器中,提起过其是一个实例方法,实例方法的特点就是:
1.方法的第一个参数必须是 self,当然这是约定俗成的写法,你可以将 self 换成 abc 之类的,但是为了别的程序员能看得懂,还是统一用 self 吧。这里的 self 代表实例本身,也就是说如果我实例化时使用的是: a = Test() ,那么 self 就代表 a 这个实例,我们可以在很多构造器中看到类似 self.scolia = 'good' 的写法,其实这个写法和在类外面 a.scolia = 'good' 效果一样,是为了添加属性,只不过 __init__ 方法是实例化时自动调用的函数,所以适合进行初始属性的创建。
2.实例方法在调用的时候,self 是自动传递的,所以不需要我们再处理。
3.实例方法一般要有实例才能调用,当然也有特殊的调用方法。
代码示例:
class Test(object):
def __init__(self, a, b): # 构造器在实例创建时进行属性的初始化
self.a = int(a)
self.b = int(b)
def abc(self, c): # 实例方法
print self.a + self.b + int(c) # 因为self是自动传递的,所以我们可以在实例方法中调用实例的属性
a = Test(123, 321) # 我们只要为 a 和 b 传参就行了
a.abc(666) # 同样的,只要为 c 传参
这里,将引入一个绑定 (binding) 的概念,其主要和方法的调用有关。
首先,我们知道方法是类的属性,而不是实例的属性,在上篇博文类的属性和实例的属性中我们也讨论过这个问题。
其次,方法只有在其所属的类拥有实例时,才能被调用。当一个类存在实例后,方法才被认为是绑定到这个实例。没有实例的时候,方法是未绑定的。
最后,任何一个方法定义的第一个参数都是变量 self ,它表示调用此方法的实例对象。
很明显这里的绑定针对的是实例方法。因为如果没有实例的话,self 就无法传递,这将导致参数的不足,当然就无法调用了。
但是,我们可以自己传递 self 来调用未绑定的方法。调用未绑定的方法通常是在我们继承了一个父类后, 我们覆盖了父类中的某个方法,但是为了实现代码重用,我们又想在子类中调用父类的方法。单纯的复制父类中的代码明显不是一个好选择, 除了浪费系统资源之外,还有可能在复制的时候出错,而且以后修改父类的代码之后,还要修改相应子类中的代码,实在太低效,这个时候就是调用未绑定方法的场景。
代码示例:
class abc(object):
def __init__(self, a):
self.a = -int(a)
class Test(abc):
def __init__(self, a, b):
abc.__init__(self, a) # 调用父类的构造器,并手动传递 self
self.b = b
def fangfa(self):
print self.a + self.b # 属性 a 由父类的构造器创建,b 由子类构造器创建
a = Test(123, 321) # 我们只创建了子类的实例,而没有创建父类的实例
a.fangfa()
本来我们没有创建父类的示例,是无法调用父类的实例方法的,但是我们手动传递了实例方法需要的 self 参数,就可以实现调用了。
这里的顺序是,我们创建了 Test 的实例,其 self 是自动传递的,故 Test 的构造方法 __init__(self, a, b) 中 self 就代表实例 a,而我们又调用了父类的 abc.__init__(self, a) 这里的 self 就是子类的实例 a ,参数 a 就是我们传的 123,而父类中 self.a = -int(a) ;最后我们可在子类的方法中调用 self.a 这个属性。
类方法:
类方法其实和实例方法类似,不过其第一个参数一般是 cls (约定俗成)而不是 self。但是,如果我们直接将 self 换成 cls 来创建类方法是不对的,因为实例方法的首个参数也是任意的,只是统一使用 self 。python的解释器并没有说看见第一个参数是 cls 就知道这个是类方法,它还是将其当作是实例方法来对待,所以我们需要通过内建函数: classmethod() 来创建类方法。
代码示例:
class Test(object):
def abc(cls):
print cls.__name__ # 打印类名
abc = classmethod(abc) # 通过普通的函数传参的方式创建类方法
a = Test()
Test.abc() # 类能调用
a.abc() # 实例也能调用
当然,有同学在看到这段代码的时候想到了装饰器,实际上我们也可以使用装饰器的方法来创建类方法:
class Test(object):
@classmethod
def abc(cls):
print cls.__name__ # 打印类名
结果也是一样的,具体选择看个人喜好。
注意,因为使用了 classmethod()函数,其第一个参数 cls 是固定传递的,而且是代表当前的类。并没有实例方法中非绑定方法的调用形式。
静态方法:
静态方法其实就是类中的一个普通函数,它并没有默认传递的参数,在创建静态方法的时候,需要用到内置函数: staticmethod() 。
代码示例:
class Test(object):
def abc():
print 'abc'
abc = staticmethod(abc)
@staticmethod
def xyz(a, b):
print a + b
Test.abc() # 类调用
Te