Python __call__总结

Python中对象按能否被调用可分为可调用对象与不可调用的对象(这不废话吗)

举一个栗子

class A(object):
    def __init__(self):
        pass
a = A()
print('A能被调用吗?',callable(A))
print('a能被调用吗?',callable(a))
#结果为:
#A能被调用吗? True
#a能被调用吗? False

这说明类对象(函数也可以的)可以被调用,而类的实例不能不调用,若想要实例对象被调用,只需在类的定义里加上__call__函数即可

class A(object):
    def __init__(self):
        pass
    def __call__(self):
        pass
a = A()
print('A能被调用吗?',callable(A))
print('a能被调用吗?',callable(a))
#结果为:
#A能被调用吗? True
#a能被调用吗? True

咦,这是咋回事?

咋回事?

我去python官方文档上查了一哈:

object.__call__(self[, args...])

Called when the instance is “called” as a function; if this method is defined, x(arg1, arg2, ...) is a shorthand for x.__call__(arg1, arg2, ...).

也就是说当实例被当作函数调用时会被调用,还有就是x(arg1, arg2, ...)和x.__call__(arg1, arg2, ...)是一样的作用的。

来个栗子会更加清楚:

class Friend(object):
    def __init__(self,name,male):
        self.name = name
        self.male = male
        print('我叫',self.name)
        print('我的性别是',self.male)
    def __call__(self,friendname):
        self.friendname = friendname
        print('我叫{},我的朋友是{}'.format(self.name,self.friendname))
a = Friend('康康','男')
a('小明')
a.__call__('小明')
#结果为:
#我叫 康康
#我的性别是 男
#我叫康康,我的朋友是小明
#我叫康康,我的朋友是小明

在例子中

a('小明') 和 a.__call__('小明') 得到的结果是一样的

a由于有__call__的存在成为了一个可以当作函数的实例。

那这个__call__就这点用处了?No No No(●ˇ∀ˇ●)

__call__作用下的装饰器

没听说过吧╰( ̄ω ̄o)

class decorator(object):
    def __init__(self,func):
        self.func = func
    def __call__(self):
        print('我是在call里被打印的')
        self.func()
@decorator  #经过装饰以后相当于test = decorator(test)
def test():
    print('我是被装饰的函数')
test()

结果就是:

我是在call里被打印的
我是被装饰的函数

牛批吧,都是血和泪的教训

当装饰器有参数时(@bala('参数'))

class decorator(object):
    def __init__(self, name):
        self.name = name
        print('传来的参数是:',self.name)
    def __call__(self, func):
        print('到我call的地盘了')
        print('传来的参数是:',func)

@decorator('parm')
def param_check():
    print('Hello')
#结果为:
#传来的参数是: parm
#到我call的地盘了
#传来的参数是: <function param_check at 0x006223D8>

分析一下:

  • 装饰器语句的参数被传递到了__init__中
  • 被装饰的函数作为参数传递到了__call__中

But加上 param_check()出现的是

class decorator(object):
    def __init__(self, name):
        self.name = name
        print('传来的参数是:',self.name)
    def __call__(self, func):
        print('到我call的地盘了')
        print('传来的参数是:',func)

@decorator('parm')
def param_check():
    print('Hello')
param_check()
传来的参数是: parm
到我call的地盘了
传来的参数是: <function param_check at 0x02C723D8>
TypeError: 'NoneType' object is not callable

 按照前面的例子来说不应该出错的,肯定是还没有弄懂它的原理。。。

看过这个文章后大致明白了一些

由于装饰器参数的存在,装饰器降了一级(看不明白吧,我也不大明白),这时只需要往__call__里在添加一个函数即可

即:

class decorator(object):
    def __init__(self,name):
        self.name = name
        print('传来的参数是:',self.name)
    def __call__(self, func):
        print('到我call的地盘了')
        print('传来的参数是:',func)
        def inner():
            func()
        return inner

@decorator('parm')  
def param_check():
    print('Hello')
param_check()
#就可得到结果:
#传来的参数是: parm
#到我call的地盘了
#传来的参数是: <function param_check at 0x035C23D8>
#Hello

就酱!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值