Почему я не могу передать сам как параметр, передаваемый по имени к методу экземпляра в Python?

Это работает:

>>> def bar(x, y):
...     print x, y
...
>>> bar(y=3, x=1)
1 3

И это работает:

>>> class Foo(object):
...     def bar(self, x, y):
...             print x, y
...
>>> z = Foo()
>>> z.bar(y=3, x=1)
1 3

И даже это работает:

>>> Foo.bar(z, y=3, x=1)
1 3

Но почему это не работает в Python 2.x?

>>> Foo.bar(self=z, y=3, x=1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)

Это делает метапрограммирование более трудным, потому что оно требует обработки особого случая. Мне любопытно, если это так или иначе необходимо семантикой Python или просто артефактом реализации.

5
задан wim 8 October 2019 в 17:58
поделиться

1 ответ

z.bar является связанным методом - у него уже есть атрибут im_self , который становится первый аргумент (условно названный self ) базового объекта функции, атрибут im_func связанного метода. Чтобы переопределить это, вам, очевидно, необходимо повторно привязать im_self ( edit : или вместо этого вызвать im_func ) - все, что вы делаете с точки зрения передачи аргументов, не конечно, повлияет на это. Да, это документированный способ работы объекта связанных методов в Python (а не просто детали реализации: каждая правильная реализация Python должна делать это именно так). Так что это «необходимо» в том смысле, что это часть того, что делает Python именно тем языком, которым он является, в отличие от того, чтобы быть немного другим или сильно отличающимся языком. Конечно, вы могли бы разработать другой язык, который будет играть по совершенно другим правилам, но - это, конечно, не будет Python.

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

TypeError: несвязанный метод bar () должен вызываться с экземпляром Foo в качестве первого аргумента ( вместо этого ничего не получил)

Правило, лежащее в основе этого очень четкого сообщения об ошибке, состоит в том, что экземпляр должен быть первым аргументом (поэтому, конечно, позиционным: именованные аргументы не имеют порядка). Несвязанный метод не «знает» (и не заботится), каким может быть имя этого параметра (и использование имени self для него является только соглашением , не правило языка Python): он заботится только об однозначном условии «первого аргумента» (среди позиционных, конечно).

Этот неясный угловой случай, безусловно, может быть изменен (с помощью патча Python 3.2, если и когда "замораживание" языковых изменений закончится ;-), серьезно усложнив несвязанные методы: им придется проанализировать и сохранить первый -аргумента во время создания и проверять аргументы ключевого слова при каждом вызове на тот случай, если кто-то передаст self по имени, а не по должности. Я не думаю, что это сломает какой-либо существующий рабочий код, это только замедлит почти все существующие программы Python. Если вы напишете и предложите патч, реализующий это усложнение, и проявите активность на python-dev, чтобы отстаивать его против неизбежной огненной бури оппозиции, у вас, несомненно, есть шанс> 0 протаранить его - удачи .

Остальные из нас, тем временем, будут продолжать получать атрибут im_func вместо этого, как один абсурдно-крошечный дополнительный шаг в том, что должно быть довольно сложным внутренним строением метапрограммирования, чтобы гарантировать такое изменение - это вовсе не «особый случай» по сравнению с ужасными трудностями адаптации передачи именованных аргументов к встроенным командам , которые не принимают именованные аргументы (и не раскрывают их «имена аргументов», позволяющие легко преобразовывать именованные аргументы в позиционные (теперь , что будет ветряной мельницей, достойной нападения, ИМХО: из всех вызываемых объектов встроенные функции хуже всего подходят для метапрограммирования из-за этого! -).

6
ответ дан 14 December 2019 в 13:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: