Python中的特殊方法:__call__

本文结构:

1.__call__方法

2.callable():判断对象/函数能否被调用

3.举例:斐波那契数列类

1.__call__方法

一个对象实例可以有自己的属性和方法,当我们调用实例方法时,我们用instance.method()来调用。

能不能直接在实例本身上调用呢?在Python中,答案是肯定的。

任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用.

看一个例子:

class Student(object):
    def __init__(self,score):
        self.score=score
    def __call__(self):
        return self.score

tim=Student(80)
tim()

##result
80

__call__大大模糊了对象和函数的边界,因为对象居然也可以调用了!

2.callable():判断对象/函数能否被调用

那么如何判断一个对象或函数能否被调用呢?可以用callable()

print callable(tim)
print callable(sum)
print callable('ABC')

##result
True
True
False

3.举例:斐波那契数列类

最后,用一个斐波那契数列类来实现一下直接调用对象。

下面这段代码定义了一个Fib类,通过将Fib类实例化创建了一个迭代器对象。

通过调用next方法,能够迭代打印数列的值。

class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1 # 初始化两个计数器a,b

    def __iter__(self):
        return self # 实例本身就是迭代对象,故返回自己
   
    '''在python2中是next,在python3中是__next__'''
    def next(self):
        self.a, self.b = self.b, self.a + self.b # 计算下一个值
        if self.a > 50: # 退出循环的条件
            raise StopIteration()
        return self.a# 返回下一个值
if __name__=='__main__':
    test=Fib()
    print test.next()
    print test.next()
    print test.next()
    print test.next()
    print test.next()

##result
1
1
2
3
5

如果觉得每次都调用next方法太过麻烦,能不能直接调用实例对象?

当然可以,只需要借助一下闭包的性质即可:

class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1 # 初始化两个计数器a,b

    def __iter__(self):
        return self # 实例本身就是迭代对象,故返回自己
   
    '''在python2中是next,在python3中是__next__'''
    def __call__(self):
        def next(self):
            self.a, self.b = self.b, self.a + self.b # 计算下一个值
            if self.a > 50: # 退出循环的条件
                raise StopIteration()
            return self.a# 返回下一个值
        return next(self)
if __name__=='__main__':
    test=Fib()
    for i in range(5):
        print test()

##result
1
1
2
3
5

相关推荐