как параметры передаются внутри `__getattr__` - PullRequest
0 голосов
/ 30 сентября 2018

Я понимаю основную функцию и пример использования метода __getattr__.Но у меня проблемы с тем, как параметры передаются внутри __getattr__.

У меня есть код

class Wrapper:
    def __init__(self, object):
        self.wrapped = object
    def __getattr__(self, attrname):
        print('trace: ' + attrname)
        return getattr(self.wrapped, attrname)


x = Wrapper([1, 2, 3])
x.append(4)
print(x.wrapped)

И он печатает

trace: append
[1, 2, 3, 4]

Простите, если мое предположение ниже неверно.Я предполагаю, что параметр 4 в x.append(4) каким-то образом передается от первоначального вызова к __getattr__, а затем к вызову метода getattr и затем к методу append класса list.Но я не уверен, что именно происходит.Может ли кто-нибудь, пожалуйста, уточнить детали.

Ответы [ 2 ]

0 голосов
/ 30 сентября 2018

__getattr__ никогда не соприкасается с этим 4.__getattr__ просто возвращает связанный метод, который затем вызывается с аргументом 4. Получение связанного метода и вызов связанного метода - это два несвязанных шага, а __getattr__ отвечает только за первый.

Может быть проще следоватьвместе, если вы мысленно разделите эту строку:

x.append(4)

на две части:

method = x.append  # obtain the bound method
method(4)          # call the bound method

Очевидно, __getattr__ вызывается в первой строке и не имеет никакого отношения ко 2-й строке.__getattr__ просто возвращает ссылку на метод append упакованного списка, так как вы можете легко убедиться сами:

>>> x.append
<built-in method append of list object at 0x7f096feb2fc8>

Это связанный метод .Связанный метод - это просто метод, имеющий ссылку на объект, который будет заменять self при вызове метода (в данном случае, список x.wrapped).Связанные методы являются причиной того, что мы можем вызывать методы без явной передачи аргумента для self.

Подробнее о связанных методах см. В чем разница между функцией, несвязанным методом исвязанный метод? .

0 голосов
/ 30 сентября 2018

Вот как я это понимаю:

x = Wrapper([1, 2, 3])

Итак, x.wrapped - это list, то есть [1, 2, 3].

Теперь, когда вы делаете x.appendВы звоните __getattr__ из Wrapper с аргументом append.Поэтому, когда python разрешает:

getattr(self.wrapped, attrname)

, он получает метод append вашего внутреннего списка, который затем возвращается.Итак, вы можете себе представить, что ваш код интерпретируется как:

# just got it outside for later explanation
l = [1, 2, 3]

x = Wrapper(l)

f = x.__getattr__('append')
# here `f` is the `append` method of `l`

f(4) # which is equivalent to `l.append(4)`

# finally
print(x.wrapped)
# which is equivalent to `print(l)`, hence the output
# [1, 2, 3, 4]

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...