Discuss / Python / 发现一个有意思的问题 , __call__ 和 __getattribute__两个方法同时去定义时会....

发现一个有意思的问题 , __call__ 和 __getattribute__两个方法同时去定义时会....

Topic source

JiliangLee

#1 Created at ... [Delete] [Delete and Lock User]

1. 单独存在__call__方法时

class count(object):
    def __init__(self, age):
        self.__i=0
        self.__age=age

    # def __getattribute__(self, att):
    #     if att=='name':
    #         return 'sorry ,i have no name.'
    #     if att=='song':
    #         return lambda: print("门前大桥下, 游过一群鸭.")

    def __call__(self):
        print('My age is %s ' % self.__age)

调用如下:

cc=count(18)
cc()
## 输出内容
My age is 18 

2. __call__和__getattribute 同时存在时

class count(object):
    def __init__(self, age):
        self.__i=0
        self.__age=age

    def __getattribute__(self, att):
        if att=='name':
            return 'sorry ,i have no name.'
        if att=='song':
            return lambda: print("门前大桥下, 游过一群鸭.")

    def __call__(self):
        print('My age is %s ' % self.__age)

调用如下:

cc=count(18)
cc()
## 输出
My age is None 

为什么call 不能好好工作了呢? 请大佬帮忙解惑.

synl古美门

#2 Created at ... [Delete] [Delete and Lock User]

注意,只有在没有找到属性的情况下,才调用__getattr__,已有的属性,比如name,不会在__getattr__中查找。

此外,注意到任意调用如s.abc都会返回None,这是因为我们定义的__getattr__默认返回就是None

synl古美门

#3 Created at ... [Delete] [Delete and Lock User]

问题与__call__方法没有关系,问题出在__getattr____getattribute__的区别,你改成__getattr__方法就没有问题了。

`__getattr__`方法是在没有找到属性的情况下才被调用

__getattribute__方法无论属性是否找到都会被调用

拿你的例子2来说:

class count(object):
    def __init__(self, age):
        self.__i=0
        self.__age=age
        print(self.__age) #这里打印看看初始化结果

    def __getattribute__(self, att):
        if att=='name':
            return 'sorry ,i have no name.'
        if att=='song':
            return lambda: print("门前大桥下, 游过一群鸭.")

    def __call__(self):
        print('My age is %s ' % self.__age)

调用如下:

cc=count(18)
cc()
## 输出
None
My age is None

类初始化方法里加上print(self.__age)

发现实例cc的属性self.__ageNone,并不是传入的参数18,这说明实例cc获取属性时调用了__getattribute__的返回结果,而在__getattribute__中没有找到属性的默认返回值是None,所以出现以上结果。

测试:将__getattribute__找不到属性的返回值设置为404

    def __getattribute__(self, att):
        if att=='name':
            return 'sorry ,i have no name.'
        if att=='song':
            return lambda: print("门前大桥下, 游过一群鸭.")
        return 404

调用结果:

cc=count(18)
cc()
## 输出
404
My age is 404

ps:上个回答是我习惯用Ctrl + Enter换行,还没编辑好就提交了。


  • 1

Reply