Python Why Does My Python Code Output None Instead of the Next Permutation?

  • Thread starter Thread starter member 428835
  • Start date Start date
  • Tags Tags
    Code Python
Click For Summary
The discussion centers on a Python code issue where the function intended to return the next lexicographic permutation outputs None instead. The problem is identified as a missing return statement in the reverse function, which is crucial for the nextPermutation function to work correctly. After adding the return statement, the code functions as expected. Additionally, there are discussions about code typos, particularly the use of capital 'I' instead of lowercase 'i', which leads to NameError. Overall, the conversation highlights the importance of ensuring functions return values and maintaining correct variable naming conventions in Python code.
  • #31
PeterDonis said:
Please post an explicit interactive session showing the case you are talking about. I have posted two interactive sessions showing what it actually takes to get Python to clone the elements of a list as well as the list itself, namely, copy.deepcopy. I am not aware of any other way of doing it.
For short lists, making copies isn't very inefficient, but you really shouldn't use deepcopy() if you don't have to.

720.000 iterations of nextpermutation(), starting with [1,2,3,4,5,6] took:
0.84s with the reverse function modifiying the list, and not returning anything from reverse()
0.91s with making a copy of the list with newlist = list[::]
1.06s using copy.copy() to make a copy of the list
3.81s using copy.deepcopy().
deepcopy still needs to examine all the objects in the list to see if any of them are lists , even if the result is the same as copy() for a list of numbers.
 
Technology news on Phys.org
  • #32
But the point is not really about cost, it is about the Principle of Least Astonishment.

If you have a function doSomethingToAList(list, moreArgs...) that does not return anything (or returns, say, an integer giving the number of entries that were affected) then it is clear that if it is going to work at all then it must mutate the list argument. You therefore know that if you don't want your list to be mutated you need to copy (or deepcopy) it first.

On the other hand you would expect a function extractMaximumValuesFrom(list, count) to return a new list with no more than [count] entries; you would NOT expect it to mutate the list argument.

pbuk said:
 
  • #33
pbuk said:
If you have a function doSomethingToAList(list, moreArgs...) that does not return anything (or returns, say, an integer giving the number of entries that were affected) then it is clear that if it is going to work at all then it must mutate the list argument. You therefore know that if you don't want your list to be mutated you need to copy (or deepcopy) it first.

On the other hand you would expect a function extractMaximumValuesFrom(list, count) to return a new list with no more than [count] entries; you would NOT expect it to mutate the list argument.
This assumes that knowing which option is the "least astonishment" option for a given function name is a simple thing. Is it?

The relevant function name in the OP is nextPermutation. Just looking at the name, would you expect this to mutate the list in place? Or would you expect it to return a new list containing the next permutation? I would expect the latter, but you were arguing earlier in the thread that this function should not return a value but should mutate the list in place, which seems to indicate that you would expect the former.
 
  • #34
PeterDonis said:
This assumes that knowing which option is the "least astonishment" option for a given function name is a simple thing. Is it?
Well-chosen names can help this.

PeterDonis said:
The relevant function name in the OP is nextPermutation.
No, the relevant function name is reverse:
pbuk said:
joshmccraney said:
Edit: all I changed was adding the return nums in the reverse function and it works. Thanks for bringing this to my attention! I appreciate it!
Yes but that was the wrong thing to fix, read on.

As this is a verb I would expect it to do something. It would be better named reversePart because that is what it does (and to avoid confusion with a list object's reverse method). A function that returned a part-reversed list would be better named getPartReversed.

PeterDonis said:
you were arguing earlier in the thread that this function should not return a value but should mutate the list in place
The point I was trying to make was that a function should not both mutate a list and return the mutated list; it should either mutate the list or return a new list. As a secondary point, I was arguing that in this case there was no advantage in returning a new list so I would choose mutation with a void return value.
 
  • #35
pbuk said:
No, the relevant function name is reverse:
Ah, yes, that's right. That one I agree would be naturally interpreted as mutating in place.

pbuk said:
The point I was trying to make was that a function should not both mutate a list and return the mutated list; it should either mutate the list or return a new list.
Yes, agreed.

pbuk said:
As a secondary point, I was arguing that in this case there was no advantage in returning a new list so I would choose mutation with a void return value.
For this particular problem, since it's only asking for the next permutation, I agree it's simpler just to mutate in place. I always tend to think in more general terms, and I can think of plenty of reasons why it would be better to return a new list in a more general purpose program. But there might also be reasons in other particular use cases to mutate in place instead.
 
  • Like
Likes pbuk

Similar threads

  • · Replies 28 ·
Replies
28
Views
4K
  • · Replies 5 ·
Replies
5
Views
2K
Replies
3
Views
1K
  • · Replies 2 ·
Replies
2
Views
2K
Replies
7
Views
2K
  • · Replies 10 ·
Replies
10
Views
2K
  • · Replies 3 ·
Replies
3
Views
1K
  • · Replies 3 ·
Replies
3
Views
3K
Replies
55
Views
6K
  • · Replies 3 ·
Replies
3
Views
3K