0

这是从Learning Python中提取和改编的代码,lambda第5行有什么用return lambda *args: '[Getattr str]',似乎print(X.__str__())期望0个参数,*args这里没有必要吗?

class GetAttr:
    def __getattr__(self, attr):
        print('getattr: ' + attr)
        if attr == '__str__':
            return lambda *args: '[Getattr str]'
        else:
            return lambda *args: None

X = GetAttr()
print(X.__call__('why', 'any', 'number', 'of', 'arguments', 'here')) 
print(X.__str__())   # but not here? 
4

4 回答 4

2

当 时attr == '__str__',函数需要返回一个可调用对象,因为__str__它应该是一个方法。简单地返回一个字符串会给你一个错误,抱怨'str'对象不可调用。

但是,*args不需要,因为__str__从不使用任何参数调用。这足以:

return lambda: '[Getattr str]'

请注意,如果您使用 python2 并按照推荐的方式继承object,则该示例不起作用。如果你使用python3,它也不起作用。这是这些情况下的输出:

getattr:__call__
没有任何
<__main__.GetAttr 对象位于 0xb728ff6c>

为什么不__getattr__调用 when attr == '__str__'

这是因为基类object已经实现了一个默认__str__方法,而我们的__getattr__函数只被缺少的属性调用。要按原样修复示例,我们必须改用该__getattribute__方法,但要注意危险

class GetAttr(object):
    def __getattribute__(self, attr):
        print('getattr: ' + attr)
        if attr == '__str__':
            return lambda: '[Getattr str]'
        else:
            return lambda *args: None

更好、更易读的解决方案是简单地__str__显式覆盖该方法。

class GetAttr(object):
    def __getattr__(self, attr):
        print('getattr: ' + attr)
        return lambda *args: None

    def __str__(self):
        return '[Getattr str]'

但是,尽管它是更好的 python,但该示例的大部分要点都丢失了。

于 2013-08-22T09:19:57.400 回答
0

它用于粉碎任何交给它的args。无论您放入多少个参数,__str__()基本上都会忽略它们。

另一方面,这是非常糟糕的 Python。你可能想尝试别的东西

于 2013-08-22T09:03:16.600 回答
0

使lambda函数返回一个函数。

于 2013-08-22T09:04:43.773 回答
0

是的,在这种情况下没有必要,因为X.__str__()总是会在没有参数的情况下调用。这取决于使用 args 错误地调用它时您想要的行为:

str1 = lambda *args: "[Getattr str]"
str2 = lambda : "[Getattr str]"

str1(1,2,3) #works, args ignored
str2(1,2,3) #throws runtime error
于 2013-08-22T09:08:21.970 回答