Reputation: 23614
I've wondered why extend/append methods of Python don't return a reference to result list. To build string of all combination of list with last element, I would like to write simple:
for i in range(l, 0, -1):
yield " ".join(src[0:i-1].append(src[-1]))
But I've got: TypeError
. Instead following code with intermediate variable is used:
for i in range(l, 0, -1):
sub = src[0:i-1]
sub.append(src[-1])
yield " ".join(sub)
Correct me please if I'm wrong
Upvotes: 0
Views: 419
Reputation: 319531
for i in range(l-1, 0, -1):
yield ' '.join(src[:i] + src[-1:])
will do.
Extend/append methods modify list in place and therefore don't return the list.
Upvotes: 0
Reputation: 881527
The reason mutating methods in Python do NOT return a reference to the object they've mutated can be found in the Command-Query Separation principle (CQS for short). Python does not apply CQS as thoroughly as Meyer's Eiffel language does (since -- as per the Zen of Python, aka import this
, "practicality beats purity"): for example, somelist.pop()
does return the just-popped element (still NOT the container that was just mutated;-), while in Eiffel popping a stack has no return value (in the common case in which you need to pop and use the top element, your first use a "query" to peek at the top, and later a "command" to make the top go away).
The deep motivation of CQS is not really "mutators should return nothing useful": rather, it's "queries should have no side effect". Keeping the distinction (be it rigidly or "as more of a guideline than a rule") is supposed to help you keep it in mind, and it does work to some extent (catching some accidental errors) though it can feel inconvenient at times if you're used to smoothly flowing "expressions and statements are the same thing" languages.
Another aspect of CQS (broadly speaking...) in Python is the distinction between statements and expressions. Again, that's not rigidly applied -- an expression can be used wherever a statement can, which does occasionally hide errors, e.g. when somebody forgets that to call a function they need foo()
, NOT just foo
;-). But, for example (and drastically different from C, Perl, etc), you can't easily assign something while at the same testing it (if(a=foo())...
), which is occasionally inconvenient but does catch other kinds of accidental errors.
Upvotes: 8
Reputation: 49793
To operate on the list and then return it, you can use the or
construction:
def append_and_return(li, x):
"""silly example"""
return (li.append(x) or li)
Here it is so that X or Y
evaluates X, if X is true, returns X, else evaluates and returns Y. X needs to be always negative.
However, if you are only acting on a temporary list, the concatenation operation already suggested is just as good or better.
Edit: It is not worthless
>>> li = [1, 2, 3]
>>> newli = append_and_return(li, 10)
>>> li
[1, 2, 3, 10]
>>> newli is li
True
Upvotes: -1
Reputation: 45071
Hm, maybe replace:
src[0:i-1].append(src[-1])
with:
src[0:i-1] + src[-1:] #note the trailing ":", we want a list not an element
Upvotes: 7
Reputation: 71939
The general reasoning is that the return type in None
to indicate the list
is being modified in-place.
Upvotes: 1