python __call__

流过昼夜 提交于 2019-12-02 15:23:33
class Enity:
#     '''调用实体来改变实体的位置。'''
    def __init__(self,size,x,y):
        self.x,self.y=x,y
        self.size=size
    def __call__(self,x,y):
        self.x,self.y=x,y

e=Enity(1,2,3)


e(4,5)
# 实例可以象函数那样执行,并传入x y值,修改对象的x y 



# 下面提供一个my_length_check()函数,用于验证name长达是否长于50个字符。
def length_check(form,field):
    if len(field.data)>50:
        raise ValidationError("less than 50")
class Myform(Form):
    name=StringField['name',[InputRequired(),length_check]]




def length(min=-1,max=-1,message=None):
    if not message:
        message='must be %d and %d'%(min,max)
    def _length(form,field):
        l = field.data and len(field.data) or 0
        if l < min or max!=-1 and l>max:
            raise ValidationError(message)
    return _length
class Myform(Form):
    name=StringField('name',[InputRequired(),length(max=50)])
# 这个length(min, max, message) 函数,调用的时候,传入了更多的参数来灵活决定校验器,
# 因为他里面就是返回一个_length的校验器,这个校验器还是遵循规则,只接受form, field 参数, 
# 但是在length() 这个外层却能接受更多参数,而这些参数也能被内层的_length()所使用。



# 使用类方法__call__实现
class Length(object):
    def __init__(self,min=-1,max=-1,message=None):
        self.min=min
        self.max=max
        if not message:
            message='must %d and %d'%(min,max)
        self.message=message
    def __call__(self,form,field):
        l =field.data and len(filed.data) or 0
        if l <self.min or self.max !=-1 and l>self.max:
            rasie ValidationError(message)
class Myform(Form):
    name=StringField('Name',[InputRequired(),Length(max=50)])
#     这次我们使用类来实现,首先实例化这个校验器Length(max=50), 这时返回的是对象实例,然后我们定义了方法__call__方法,说明实例对象是可以调用的, 最后的结果就是Length(max=50)(form, field)。
# 这样实现方法是也是很妙的。
# 说到这里,类实现方法跟闭包很像,都是把变量封装起来,让真正的校验器能读取到参数。

# 闭包避免了使用全局变量,此外,闭包允许将函数与其所操作的某些数据(环境)关连起来。
# 这一点与面向对象编程是非常类似的,在面对象编程中,对象允许我们将某些数据(对象的属性)与一个或者多个方法相关联。




class Counter:
    def __init__(self,func):
        self.func=func
        self.count=0
    def __call__(self,*args,**kwargs):
        self.count +=1
        return self.func(*args,**kwargs)
@Counter
def foo():
    pass
for i in range(10):
    foo()
print(foo.count)
#记录调用次数
# 首先这里的@Counter是装饰器,执行起来顺序是 foo = Counter(foo), 
# 实例化,把foo函数传到类Counter里面,并存到对象属性里面,
# 然后返回foo = Counter实例。 这时foo已经是Counter实例,而不是本身foo函数。
# 当执行foo()的时候,其实已经变成了,执行__call__函数,
# 而这个函数里面是执行了本身的self.func 即foo的实际逻辑, 而且加上了计算调用次数。这样就记录状态了。


10


 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!