Why does Python use methods for some functionality (e.g. list.index()) but functions for other (e.g. len(list))?: "For some operations, prefix notation just reads better than postfix — prefix (and infix!) operations have a long tradition in mathematics which likes notations where the visuals help the mathematician thinking about a problem. "

Semi-agreement.

I like readable and familiar notations. I like notations familiar from math.

But I note that math also has postfix notations, such as factorial n!. Double factorial or involutions n!!. n# - commonly product of primes up to n. I argue that % is a postfix operator (that divides by 100).

And how about situations where the operator symbols surround their arguments: absolute value and cardinality |a|. Also the open/closed interval notations (lo,hi) [lo,hi] [lo,hi). Let alone ]a,b(, etc.

Arguably the complement of a set A^C is a postfix operator - but really is is a superscript operator.) Math also makes great use of two dimensions, subscripts and subscripts, both to left and right. (

Myself, I prefer the approach - I think it was Algol-68 - where an operator could be applied both prefix or postfix (and occasionally infix, and other fixes).

To apply a function f to an argument value x, write

prefix

f :- x

postfix

x -: f

Above I have used :- and -: as my function apply operators, deliberately using unfamiliar notation. Familiar notation might be

f . x

or simply putting things next to each other

f x

in published math, usually in different fonts (which are essentially a type system).

To apply a function f to an argument list (x,y), write

prefix

f :- (x,y)

postfix

(x,y) -: f

infix

x --: f :-- y

To apply a function f to an argument list (x,y,z,...), write

prefix

f :- (x,y,z,...)

I myself don't like SmallTalk or AppleTalk like polyfix

f: x: xval y: yval z: zval

at least not beyond keyword parameters

f :- (x=xval, y=yval, z=zval, ...)

With the usual elision and shortenings

prefix

f :- x

==> f. x

==> f of x

==> f(x)

postfix

x -: f

==> x's f

===> x | f (stretching to use a UNIX-like pipe notation)

infix

x --: f :-- y

==> x .f. y

===> x .+. y

==> x + y (if the operator f or + is syntactically defined to be infix)

I suppose that allowing different *fixes for the same function goes against Python's "there should be only one way to do it" philosophy.