Различия между переменным синтаксисом при вызове метода в списке

AnriSonohara спросил: 13 июня 2018 в 07:15 в: python

Если у меня есть

things = ["Dog", "Zebra", "Cow"]

, в чем разница между

things.pop()

и

pop(things)

обрабатывает ли Python3.6 их по-другому? Есть ли разница между этими двумя?

3 ответа

Есть решение
blhsing ответил: 13 июня 2018 в 07:27

pop не является встроенной функцией Python. В вашем примере работает только things.pop().

С другой стороны, если вы спрашиваете о list.pop(things), то да, он идентичен things.pop().

Хотя list.pop(things) немного читается, чем things.pop() и поэтому не рекомендуется вообще, list.pop может быть полезна, когда вы использовать его как функцию для определенных операций на основе итератора. Например, следующее дает вам список последнего элемента каждого под-списка списка:

>>> a=[[1, 2, 3],[9, 8, 7]]
>>> list(map(list.pop, a))
[3, 7]
>>>
abarnert ответил: 13 июня 2018 в 07:38

Если вы задаете конкретный вопрос о pop, ответ тривиален: нет функции с именем pop. Итак, если вы попробуете pop(things), вы получите NameError.

Конечно, вы всегда можете написать свою собственную функцию pop:

def pop(seq, *args, **kw):
    return seq.pop(*args, **kw)

И теперь, конечно, pop(things) и things.pop() будут делать то же самое. Но разница в том, что первая вызывает вашу функцию pop, которая вызывает метод, в то время как последняя просто вызывает метод.


Если вы запрашиваете больше общий вопрос о том, поддерживает ли Python UFCS ("синтаксис вызова единой функции"), где вызовы функций, такие как f(x, a, b), автоматически превращаются в вызовы методов, такие как x.f(a, b) 1 , если необходимо, тогда ответ - нет, Python этого не делает.

Некоторые другие языки. В основном это языки с поддержкой C ++, такие как D и Rust. 2 В C ++ свободные функции являются "частью интерфейса" типа, а C ++ имеет всевозможные сложные функции, такие как поиск Koenig, оболочку для операторов и т. д., чтобы сделать эту работу, а UFCS - гораздо более простой и обычно более читаемый способ сделать это.

UFCS имеет меньше смысла в динамически типизированном языке, но периодически появлялись предложения добавить его Python в любом случае. См. Это обсуждение рассылки.

Направление напротив , UMCS ("Единый метод вызова синтаксиса"), где x.f(a, b) превращается в f(x, a, b), имеет немного больше смысла, когда поиск x.f завершается с ошибкой, это легко подхватить с помощью __getattr__ (который естественно вписывается в динамический поиск под управлением Python Smalltalk) , И есть библиотеки вроде funcall, с которыми вы можете играть, если вам интересно (хотя я не знаю никакого готового к выпуску решения).


1. ... или, возможно, type(x).f(x, a, b). Это не совсем то же самое, но для любого типа normal , например list, они будут иметь тот же эффект, что и в blhsing , а для типов, которые делают что-то странное, поэтому они отличаются друг от друга, я думаю, что вызов метода unbound может быть более вероятным, чем вы хотите.

2. Были также предложения добавить его в C ++, возвращаясь к C ++ 0x дням. Я полагаю, что текущая версия - N4174 от Stroustrop, неполный обзор / сводка, и последующее рассмотрение было перенесено на C ++ 17, но может быть рассмотрено снова.

Tim Pietzcker ответил: 13 июня 2018 в 07:19
>>> things = ["Dog", "Zebra", "Cow"]
>>> things.pop()
'Cow'
>>> pop(things)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'pop' is not defined

Итак, да, есть разница. Интересно, почему вы думаете по-другому?