2013-08-22 3 views
0

Код, извлеченный и адаптированный для обучения Python, используется lambda в строке 5 return lambda *args: '[Getattr str]', кажется print(X.__str__()) ожидать 0 аргументов, *args здесь не нужно?Что такое лямбда в этом коде python?

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? 

ответ

2

Когда attr == '__str__', функция должна возвращать вызываемый объект, потому что __str__, как ожидается, будет методом. Простое возвращение строки даст вам сообщение о том, что объекты 'str' не подлежат вызову.

Однако *args не требуется, так как __str__ никогда не вызывается никакими аргументами. Этого достаточно:

return lambda: '[Getattr str]' 

Обратите внимание, что если вы используете python2 и наследовать от object, как рекомендуется, пример не работает. И если вы используете python3, это тоже не сработает. Это выход в тех случаях:

 
getattr: __call__ 
None 
<__main__.GetAttr object at 0xb728ff6c> 

Почему не __getattr__ вызывается, когда attr == '__str__'?

Это потому, что базовый класс object уже реализует метод по умолчанию __str__, и наша __getattr__ функции вызывается только для отсутствует атрибутов. Чтобы исправить пример, мы должны использовать метод __getattribute__, но beware of the dangers.

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

А лучше и более читаемым решением было бы просто переопределить метод __str__ в явном виде.

Но, хотя это лучший питон, большая часть примера проиграна.

0

Его предназначение для раздавливания любых аргументов, переданных ему. Независимо от того, сколько аргументов вы помещаете в __str__(), он всегда будет игнорировать их в основном.

С другой стороны, это ужасно написанный питон. Возможно, вы захотите попробовать что-то другое.

0

lambda заставляет функцию возвращать функцию.

0

Да, в этом случае нет необходимости, так как X.__str__() всегда будет вызываться без аргументов. Это зависит от того, какое поведение вы хотите, когда он неправильно вызывается с аргументами:

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

str1(1,2,3) #works, args ignored 
str2(1,2,3) #throws runtime error 
Смежные вопросы