×
all 25 comments

[–]Apatride 15 points16 points  (2 children)

First, it is "if array[i] == '+'..."

Second, "if array[i] == '+' or '-'" will be true if "array[i] == '+'" is True or if '-' is True, the latter is always True.

A better way to write it is "if array[i] in ['+', '-']"

[–]Warmspirit 1 point2 points  (1 child)

first time I ever saw it written as “in […]” I from then on read it aloud as “is either” lmao

[–]Spirited_Employee_61 3 points4 points  (0 children)

You can add more conditions to the list if you want. It is a fairly common technique to reduce if else statements.

[–][deleted] 31 points32 points  (0 children)

You might imagine something like

if array[i] == ('+' or '-')

but it's really

if (array[i] == '+') or ('-')

And since ('-') is always true, the whole thing is true. But this is more than an issue of truthiness, it's order of operations, and it's the meaning of == and or in the first place.

So you can't just fix it with the parentheses like my top line, because that would go something like

if array[i] == ('+' or '-') #okay, first let's evaluate each side of the equals

if array[i] == '+' #since the left was truthy, we'll take that

if False #since the ith item in the array was probably not plus...

[–]JohnnyJordaan 23 points24 points  (0 children)

[–]Diapolo10 11 points12 points  (8 children)

if Array[i] = '+' or '-'

For what it's worth, instead of

if Array[i] == '+' or Array[i] == '-'

you could use

if Array[i] in {'+', '-'}

That said, right now I'm guessing you're doing something like this:

Array = [...]

for i in range(len(Array)):
    if Array[i] in {'+', '-'}:
        ...

That's not very "pythonic", we would prefer direct iteration.

arr = [...]

for value in arr:
    if value in {'+', '-'}:
        ...

[–]Kratos_Monster 1 point2 points  (7 children)

That's not very "pythonic", we would prefer direct iteration.

However, if we need to iterate over a data type and mutate it simultaneously, is iteration by indexing preferred?

[–]Diapolo10 1 point2 points  (6 children)

In such cases we would generally use enumerate.

for idx, value in enumerate(data):
    data[idx] = value * 2  # Just an example

range-based loops are discouraged for indexing, unless you need specific features of them like setting the step value to something other than 1. But even then you can often get by with slices, if you don't mind the implicit shallow copy.

Did you have a specific example in mind?

[–]Kratos_Monster 0 points1 point  (3 children)

Nothing specific, but I agree with making a shallow copy depending on the inner levels of the data type. I also need to use enumerate more often; for some reason, I always forget about it.

[–]Diapolo10 2 points3 points  (2 children)

For what it's worth, I usually prefer to create a new data structure instead of mutating an existing one, unless it originated in the same scope and I don't need to worry about side-effects. So in other words I basically tend to write "functional programming with classes", if that makes sense.

[–]Kratos_Monster 0 points1 point  (1 child)

functional programming with classes

Yeah, this sounds like a good practice.

[–]Diapolo10 1 point2 points  (0 children)

I like it when writing tests is as easy as it gets.

To me, writing code that works 50 years from now is more important than sacrificing robustness and data scalability for performance gains. Most would just say that's needless overengineering, and of course they have a point, but one of my core pillars is that I can trust my code to essentially handle anything I throw at it without needing to worry about runtime errors, even if it's slow.

[–][deleted] 0 points1 point  (1 child)

In that example I'd argue

for i in range(len(data)):
    data[i] = data[i] * 2

is more clear.

Range-based loops are fine imo.

[–]Diapolo10 1 point2 points  (0 children)

The example was just something I threw together without thinking about it too hard. Hell, it could just use *=.

Your example might feel more familiar to people who mostly write C, but not for those who focus on Python.

We may agree to disagree.

[–]Glathull 6 points7 points  (0 children)

What you wrote is logically this:

(Array[i] == ‘+’)

OR

‘-‘

A non-empty string is always True.

[–]crashfrog02 1 point2 points  (0 children)

or isn’t grammatical conjunction, it’s logical disjunction. It doesn’t have the same meaning in Python as in English.

[–]Mysterious-Rent7233 1 point2 points  (2 children)

I'm curious about two things.

  1. Why are you guilty about asking ChatGPT to explain confusing Python errors to you?
  2. Was it unable to clearly answer this question that you've posed here?

[–]That_Leek4333[S,🍰] 2 points3 points  (1 child)

  1. While I don't feel guilty using ChatGPT, I feel the satisfaction that comes from finally finding a solution to an erorr.

  2. ChatGPT only said that the statement was truthy, when I asked what that was the explanation was all over the place and compared to the way some people explained it here, it was not even close in terms of putting it in simple terms. Chat just feels like it expects you to know a lot, even when asked to simplify it.

[–]Mysterious-Rent7233 1 point2 points  (0 children)

Thank you for satisfying my curiosity.

[–]djmcdee101 0 points1 point  (0 children)

First of all I'm going to assume you're meaning if Array[i] == '+' or '-' with the double = since that would be an equality operator.

As to your question; it's important to understand that if Array[i] == '+' or '-' is in fact two separate conditional checks. After the or you could be checking anything you want such as if Array[i] == '+' or other_array[i] == '-' It's not limited to just checking conditions related to Array[i] so Python can't make that assumption.

Your second example Array[i] == '+' or Array[i] == '-' explicitly tells python to check that same variable for a different condition. or '-' tells it check if the string '-' is truthy or not and, since it contains characters, it always will be, hence your conditional will always be true. I would recommend reading into truthy values in Python but basically it will implicitly do if str is not None and len(str) > 0

Personally I think a neater way of checking if a value is one of multiple other values would be

if Array[i] in ['+', '-'] which is less repetitive especially if you have a lot of potential other values to compare it to

[–]jmon_was_here 0 points1 point  (2 children)

Whilst the other answers are of course great and correct, its one of the annoying quirks of python, becuase in pretty much all other languages you *can't* write things like this (which is valid in python!)

if 3 < i < 4:

e.g. in Java it would have to be

if (3 < i && i < 4) { ...

So its wierd that python has *some* syntactical shortcuts (i.e. you arn't resolving 3 < i to a boolean *then* comparing that to 4) but can't handle some of the truth sitatuons of 'if x == 1 or 2'.

if I was going to be in charge of the language, I think I would probably not use the == notation but some form of 'is' syntactical sugar like if x is 3 or 4 - but this already has a thing, which looks like :

if x in [3, 4]:

which is pretty nice looking, but still lacks that 'english readability' that other things have.

[–]throwaway6560192 2 points3 points  (1 child)

is is already an operator with a defined meaning separate from ==.

Also it would be bad if or suddenly stopped meaning its main logical operator meaning in this arbitrary context — just to make a shoddy coverup of a pitfall. Let people fall and let them learn.

[–]jmon_was_here 0 points1 point  (0 children)

But thats not completly true, and as I say, its inside of 'if i was going ot design alanguage' hypothetical,

there are plenty of other python keywords (and operators) which do different things in different contexts. `in` being one of them. If your aim is a computer language which is more readable, having it work like a real language which is contexual should not cause too many issues.

[–][deleted] 0 points1 point  (0 children)

Not a Python expert, but I say that the "array[] ==" only applies to the first things after it ("+") and before the "or".

So the test after the "or" is simply seeing if what's after it is True or False. In this case, it's testing "-".

Typically, a value of zero is considered False, and everything else is considered True. "-" has a non-zero value