This has really not been true since python grew a ternary operator, syntactically you can write functional code perfectly fine in python -- the only significant syntactic shortcoming is lack of pattern matching.
What actually hampers functional expression is semantics and mostly two-fold:
1. functions are terribly slow and always grow stack, so cannot replace iterative constructs.
2. Although python actually comes with a fair amount of functional data structures out of the box (str, bytes, tuple, frozenset, namedtuple, ...) none of them can be "updated" efficiently.
There are some other things (exception as opposed to sum-type based error handling), but fixing the above would be enough to write functional code pretty unhampered, I think.
> Although python actually comes with a fair amount of functional data structures out of the box (str, bytes, tuple, frozenset, namedtuple, …) none of them can be “updated” efficiently.
If they can’t be updated efficiently, they are just immutable than particularly functional.
Of course I agree that calling such data structures immutable is more precise, but it's still in contrast to both imperative programming and imperative data structures. In particular every single functional language (including the purest of the pure) fairly heavily use immutable array based structures in one way or other. So if functional programming requires only using data structures with structural sharing, there are no functional programming languages.
What actually hampers functional expression is semantics and mostly two-fold:
1. functions are terribly slow and always grow stack, so cannot replace iterative constructs.
2. Although python actually comes with a fair amount of functional data structures out of the box (str, bytes, tuple, frozenset, namedtuple, ...) none of them can be "updated" efficiently.
There are some other things (exception as opposed to sum-type based error handling), but fixing the above would be enough to write functional code pretty unhampered, I think.