# Revision history [back]

Hello, @Cyrille! Let me answer the second part of your question. The problem with the syntax

cand1 = cand.remove(Nanson_one(cand, partisans,3))


is that cand.remove() is a statement, but not an expression. Generally speaking (not formally), statements are instructions given to the language to perform a task, like print('Hello, world') or 2 + 3, while expressions are all those statements that return a value. For example, print('Hello, world') does not return any value (it just prints the words "hello, world"), while 2 + 3 returns the value 5.

Now, this previous explanation is not 100% true. Python actually has the None value for statements that are not expressions (confusing, I know). However, this is a quite useful feature, since it can help you know if a particular statement is an expression. For example, if you write

print(2 + 3)


you will see the value 5, indicating that 2 + 3 (not print(2 + 3)) is an expression. However, if you write

A = [1, 2, 3, 4]
print(A.remove(3))


you will see None in your screen, indicating this is not an expression. This means A.remove(3) performs the task of removing the 3 from the list A, but does not return any value as a result.

That's the problem with your statement

cand1 = cand.remove(Nanson_one(cand, partisans,3))


since it is removing the less voted candidate from the list cand, and then it does not return any value (actually returns None, as just explained), which is assigned to cand1, so cand1 is None or nothing.

The solution is to separate the operation into two lines:

cand.remove(Nanson_one(cand, partisans,3))
cand1 = cand


Now, this also causes some problems: you should be very careful about aliasing. Let me explain really quickly. Consider this code:

A = [1, 2, 3, 4]
B = A
A.remove(3)
print('A =', A)
print('B =', B)


Intuitive thought suggest that $A = [1, 2, 4]$ and $B = [1, 2, 3, 4]$ after this code is executed, but that is not correct (try it!). Lists, like A and cand are mutable data types, which means that B = A does not create a copy of A and assigns that copy to B, but actually creates a "new name" or "alias" for A. In simple terms, A and B are the same list, and modifying one of them, modifies the other in the same way, and viceversa. If you want to avoid aliasing, you should write

A = [1, 2, 3, 4]
B = A[:]
A.remove(3)
print('A =', A)
print('B =', B)


The choice of aliasing vs. not aliasing is a matter of what you want your code to do. Unfortunately, I don't have enough information about your code to help you with that. (Perhaps it is even unnecessary to consider this.)

Anyway, concerning the first part of your question, I am not completely sure if this is what you want, but I believe that you want something like this code. (Note: I made some modifications to your code in order to make it easier for me to program it.) If this is indeed the code you need, please, let me know so I can add it here with an explanation.

I hope this helps!

Hello, @Cyrille! Let me answer the second part of your question. The problem with the syntax

cand1 = cand.remove(Nanson_one(cand, partisans,3))


is that cand.remove() is a statement, but not an expression. Generally speaking (not formally), statements are instructions given to the language to perform a task, like print('Hello, world') or 2 + 3, while expressions are all those statements that return a value. For example, print('Hello, world') does not return any value (it just prints the words "hello, world"), while 2 + 3 returns the value 5.

Now, this previous explanation is not 100% true. Python actually has the None value for statements that are not expressions (confusing, I know). However, this is a quite useful feature, since it can help you know if a particular statement is an expression. For example, if you write

print(2 + 3)


you will see the value 5, indicating that 2 + 3 (not print(2 + 3)) is an expression. However, if you write

A = [1, 2, 3, 4]
print(A.remove(3))


you will see None in your screen, indicating this is not an expression. This means A.remove(3) performs the task of removing the 3 from the list A, but does not return any value as a result.

That's the problem with your statement

cand1 = cand.remove(Nanson_one(cand, partisans,3))


since it is removing the less voted candidate from the list cand, and then it does not return any value (actually returns None, as just explained), which is assigned to cand1, so cand1 is None or nothing.

The solution is to separate the operation into two lines:

cand.remove(Nanson_one(cand, partisans,3))
cand1 = cand


Now, this also causes some problems: you should be very careful about aliasing. Let me explain really quickly. Consider this code:

A = [1, 2, 3, 4]
B = A
A.remove(3)
print('A =', A)
print('B =', B)


Intuitive thought suggest that $A = [1, 2, 4]$ and $B = [1, 2, 3, 4]$ after this code is executed, but that is not correct (try it!). Lists, like A and cand are mutable data types, which means that B = A does not create a copy of A and assigns that copy to B, but actually creates a "new name" or "alias" for A. In simple terms, A and B are the same list, and modifying one of them, modifies the other in the same way, and viceversa. If you want to avoid aliasing, you should write

A = [1, 2, 3, 4]
B = A[:]
A.remove(3)
print('A =', A)
print('B =', B)


The choice of aliasing vs. not aliasing is a matter of what you want your code to do. Unfortunately, I don't have enough information about your code to help you with that. (Perhaps it is even unnecessary to consider this.)

Anyway, concerning the first part of your question, I am not completely sure if this is what you want, but I believe that you want something like this code. (Note: I made some modifications to your code in order to make it easier for me to program it.) If this is indeed the code you need, please, let me know so I can add it here with an explanation.explanation. Also, let me know if you require some specific modification.

I hope this helps!

Hello, @Cyrille! Let me answer the second part of your question. The problem with the syntax

cand1 = cand.remove(Nanson_one(cand, partisans,3))


is that cand.remove() is a statement, but not an expression. Generally speaking (not formally), statements are instructions given to the language to perform a task, like print('Hello, world') or 2 + 3, while expressions are all those statements that return a value. For example, print('Hello, world') does not return any value (it just prints the words "hello, world"), while 2 + 3 returns the value 5.

Now, this previous explanation is not 100% true. Python actually has the None value for statements that are not expressions (confusing, I know). However, this is a quite useful feature, since it can help you know if a particular statement is an expression. For example, if you write

print(2 + 3)


you will see the value 5, indicating that 2 + 3 (not print(2 + 3)) is an expression. However, if you write

A = [1, 2, 3, 4]
print(A.remove(3))


you will see None in your screen, indicating this is not an expression. This means A.remove(3) performs the task of removing the 3 from the list A, but does not return any value as a result.

That's the problem with your statement

cand1 = cand.remove(Nanson_one(cand, partisans,3))


since it is removing the less voted candidate from the list cand, and then it does not return any value (actually returns None, as just explained), which is assigned to cand1, so cand1 is None or nothing.

The solution is to separate the operation into two lines:

cand.remove(Nanson_one(cand, partisans,3))
cand1 = cand


Now, this also causes some problems: you should be very careful about aliasing. Let me explain really quickly. Consider this code:

A = [1, 2, 3, 4]
B = A
A.remove(3)
print('A =', A)
print('B =', B)


Intuitive thought suggest that $A = [1, 2, 4]$ and $B = [1, 2, 3, 4]$ after this code is executed, but that is not correct (try it!). Lists, like A and cand are mutable data types, which means that B = A does not create a copy of A and assigns that copy to B, but actually creates a "new name" or "alias" for A. In simple terms, A and B are the same list, and modifying one of them, modifies the other in the same way, and viceversa. If you want to avoid aliasing, you should write

A = [1, 2, 3, 4]
B = A[:]
A.remove(3)
print('A =', A)
print('B =', B)


The choice of aliasing vs. not aliasing is a matter of what you want your code to do. Unfortunately, I don't have enough information about your code to help you with that. (Perhaps it is even unnecessary to consider this.)

Anyway, concerning the first part of your question, I am not completely sure if this is what you want, but I believe that you want something like this code. (Note: I made some modifications to your code in order to make it easier for me to program it.) If this is indeed the code you need, please, let me know so I can add it here with an explanation. Also, let me know if you require some specific modification.

I hope this helps!

Edit: The previous code answers the question only partially. Unfortunately, I haven't found a practical way to add labels to the interactive cells in the SageCell Server. Doing this seems easier in a local Sage installation running Jupyter(Lab); however, I believe that's the for the purposes of another question.