Here is simple ST plugin. Is there a difference between commented lines? Personally, I don't see any difference in how they work, just a difference in visual appearance.
However, some plugin developers prefer second version (== 1), which looks just useless and ugly for me. Probably there are some reasons to prefer it?
import sublime_plugin
class ExpandUnexpandTabsCommand(sublime_plugin.EventListener):
def on_pre_save(self, view):
# if view.settings().get("translate_tabs_to_spaces"):
# if view.settings().get("translate_tabs_to_spaces") == 1:
# if view.settings().get("translate_tabs_to_spaces") == True:
view.run_command("expand_tabs")
else:
view.run_command("unexpand_tabs")
This is covered in PEP8, the official Python style guide's, "Programming Recommendations" section:
Don't compare boolean values to True or False using ==.
Yes: if greeting:
No: if greeting == True:
Worse: if greeting is True:
In other parts of the guide, they emphasize this for other use cases (e.g. testing for empty/non-empty collections should not use len()); unless a specific value is critical to your logic, use the implicit boolean nature of what you're testing (with not if it must be inverted), don't spin your wheels with comparisons that ultimately add little in terms of readability, increase fragility, and slow your code to boot.
The only reason to prefer the other approaches is if you expect there to be other truthy values that should not count as truthy. In this case, the translate_tabs_to_spaces setting is very clearly boolean in nature, so you almost certainly want to handle any truthy value the same way; if they later redesigned the setting to have a numeric value, where 0 meant "don't translate" and any positive value meant the number of spaces each tab was worth, implicit truthiness evaluation would continue to work, but for the standard four space indents, a test for == 1 or == True would suddenly decide no translation was occurring.
It depends on what the possible values are.
If the file must have 0 or 1 in it, anything else is an error, and you're reading it as an int, then you probably want == 1.
If the file can have either True or no entry at all, and you're using get(…) instead of [] so you get back None whenever it's not True, then you want to just test the truthiness. (Or maybe is not None, but definitely not == True or == 1.)
The rule is pretty simple: when writing a test, write what you mean to test.
Different tests mean different things:
if spam:: passes if spam is anything truthy. That means anything besides None, False, numeric zero, or empty containers.
if spam == 1:: passes if spam is the number 1.
if spam is True:: passes only if spam is the special constant True. If you want to make sure other truthy values fail, and only True counts, use is. You rarely want this.
if spam == True:: passes if spam is the special constant True, or some object equal to it. If you've gone out of your way to write a class whose __eq__ tests for True or something, then you might want this test, but it's hard to imagine why you would otherwise.
It happens to be true that 1 == True. But writing == True when you want to test for the number 1, or == 1 when you want to test for True but not other truthy values, is misleading to anyone who understands idiomatic Python, and mildly confusing to anyone who doesn't, and there's no benefit to anyone. So don't do it.
And writing either of those when you want to test for anything truthy isn't just misleading, it's wrong.
if view.settings().get("translate_tabs_to_spaces") is more concise and readable. There is little if ever any need to compare a Boolean to another Boolean value, and using integers of 0 and 1 to denote a Boolean value should only be considered when the programming language does not support Boolean values.
Related
As a begineer coder, I wrote a program, something along the lines of:
ArbitraryVariable = 1
--Code--
--Code--
--Code--
If ArbitraryVariable == 1:
--Code--
--Code--
--Code--
I would set ArbitraryVariable to 1 if I wanted it to do that thing, and anything else (usually 0) if I didn't, which i guess accomplishes a de facto true/false logic.
My friend who actually knows what he's doing informs me this would've been better accomplished with a boolean as it's true/false, which makes sense, but I am curious if there is actually any specific benefit to doing this, other than a very slight increase in optimisation and it seemingly just being the boolean's 'thing'?
I wrote this in python, but feel free to answer across languages.
this is a great question.
Boolean is used for values that only require the true/false data types. If I'm honest it's mostly used because of coding standards that most programmers use. As you mentioned there is a slight performance increase over using an integer to denote true or false.
It also provides the positive of being easier to read and understand, you don't need operators in python if you use a boolean value. You can just do this;
Boolean = True
if Boolean:
print("True")
and if it's false you can just use;
Boolean = False
if not Boolean:
print("False")
Overall, the one you used should be depending on what the if statement is doing. If the question is something like Is the light on? true and false would be an appropriate answer. That's what I've found in my experience anyway.
The question I'm about to ask here has been asked before, but those questions/answers make no mention of what I want to know.
I recall a few months or so ago, I had a rather sizable Python script, and I was using if x: because it was shorter and I was lazy. I don't remember which version of Python, but I do remember getting a DeprecationWarning (or PendingDeprecationWarning?) about implicit comparisons to True.
Now, I'm trying to write something someone else might read. I'm using if x == True and if x is not None everywhere, and pep8 and pylint are complaining about this, saying I should use if x:.
Personally, I think if x: is far less readable, but pep8 (the program) and PEP 8 (the document) both disagree.
Google is not being very helpful in allowing me to figure in which version, if ever, Python gave a DeprecationWarning for if x:, so I wonder if perhaps the SO community can provide insight.
Should I be worrying about this at all? Does it actually matter that much?
The correct answer as to what condition to use is, in the first place, a matter of semantics rather than style. Unless x is a boolean value, 0/False or 1/True, which your question did not specify, if x: and if x == True: are semantically different conditions and often give different results. You should use whichever is the correct one for the situation. if x: is usually the correct choice, but not always. If x is specified (known) to be a boolean, then adding == True is superfluous and a waste of time for the writer, reader, and interpreter.
Under the covers, if x: means (is implemented as) if bool(x) is True in the normal meaning of this expression, and if x == True: means if bool(x == True) is True. Since x == True return a bool and bool(a_bool) is a_bool, the latter reduces to if (x == True) is True. In general, bool(x) is not the same as x == True.
if x is None: (or not None) should be used if and only if that is the proper condition. It often correct when testing the output of a function returns either an int (or string or ...) or None. In many other situations, it is usually wrong.
It is perfectly good Python, and Python 3.+ versions don't give a warning, so if you're writing code for other people to work with in the future, using if x: is perfectly fine. And by the way, on behalf of every developer who had to maintain horribly unreadable code, THANK YOU for considering the readability of your code.
I think you have several separate issues confused.
It's best to check what the style guide actually says, and double check how your code actually behaves, rather than relying only on remembered behaviour :-)
Boolean expressions are already either true or false
The expression in an if statement is always intepreted as boolean; anyone reading Python code needs to know that anyway.
So the following all mean exactly the same thing, and piling on == True does not improve readability:
if x + y:
…
if (x + y) == True:
…
if ((x + y) == True) == True:
…
if (((x + y) == True) == True) == True:
…
which is why PEP 8 says:
Don't compare boolean values to True or False using == .
Singletons should be compared using identity
The comparison of an object to None implies that value is treated specially; it is commonly used as a sentinel for special processing. It is a singleton, so comparing whether an object is merely equal to None is ambiguous.
So, if your intent is to test a value for None, you should test whether the object is none by testing its identity:
if x is None:
…
if x is not None:
…
which is why PEP 8 says:
Comparisons to singletons like None should always be done with is or is not , never the equality operators.
None is not the only value that is boolean false
There are many values which are false in a boolean context, so doing a mere if x: is not enough to tell whether an object is actually None.
Which is why PEP 8 says:
beware of writing if x when you really mean if x is not None -- e.g. when testing whether a variable or argument that defaults to None was set to some other value.
In /tmp/spam.py:
n = 69
if n == True:
print 'potato'
pep8 utility complains about this conditional:
wim#SDFA100461C:/tmp$ pep8 spam.py
spam.py:3:6: E712 comparison to True should be 'if cond is True:' or 'if cond:'
the first suggestion is wrong/"worse" according to pep8 itself
the second suggestion changes the behaviour of the code
What is the best practice for a case where you actually do want to check equality with True? Is identity checking with True using is OK? Why does pep8 utility offer an alternative which is explicitly discouraged in pep8 itself?
If you really do need to check equality with True then use == and ignore PEP8, but in almost any conceivable case that isn't what you want.
If you want to know whether the value you have is one of the values Python considers to be true, use if cond:. If you want to know whether the value you have is the singleton value True then use is True, the booleans True and False are singletons so it is correct to use is in this situation.
If you need to test whether your object is the singleton True, but a linter or a code reviewer complains about is True, then isinstance(x, bool) and x is a behaviorally equivalent (but slower) substitute.
Checking x == True is a halfway house. It is true when x is True is true, and false for your case of x=69, but there are other objects which are not themselves True but for which x==True gives an unexpectedly true result such as 1 == True being true. (thanks #Ant).
So putting that together:
value of n: True 1 69 False 0
-----------------------------------------------
expression result
-----------------------------------------------
if n: True True True False False
if n is True: True False False False False
if n==True: True True False False False
Pick the row from that table which gives the results you really wanted (and the last one isn't it).
Whatever you do, I think a comment is required since the code looks funny.
If you want to check equality with True then it might be clearer to write if n == 1. Someone reading the code is less likely to misinterpret it as an attempt to test logical truth.
Of course if n has a user-defined type it's possible to define n.__eq__ such that (n == True) != (n == 1), but it would be pretty nasty. So you'd have to decide whether the subtle difference in meaning is justified by the benefit of avoiding the code looking like an incorrect logical truth test.
If the difference is not justified, and if you're absolutely required to write to the PEP8 style guide, then either use assertEqual or write expected_value = True, if n == expected_value.
If the code is a unit test for an API that for some reason defines specifically that the literal True is returned, then of course you should test if n is True, not if n == True. As before, a comment or some indirection would be needed to stop the code looking wrong.
Another option is to change the API you're testing. The reason for the style guide rules is in part to discourage people from inventing or relying on APIs that specifically define that the return value must be identical or equal to the literal True, and instead define APIs and write their code in terms of logical truth. So if you "fix" the API you can "fix" the code that tests it.
Why do you need to explicitly test for True values? You rarely, if ever do need narrow your test down to a specific type. I'd rethink your use case here; if you are building an API that'll return a bool instead of in int for out-of-band conditions, then use exceptions instead.
If you do have to test for True only, then use
if n is True:
because the boolean values are meant to be singletons like None. See the Programming recommendations section:
Comparisons to singletons like None should always be done with is or is not, never the equality operators.
Moreover, because issubtype(bool, int) is true (for historical reasons; bool was introduced rather late in Python), n == True is also true for n = 1, if you can only accept True here then you can only use is True. You could also use isinstance(n, bool) and n, which would allow for subclasses of bool, but I cannot imagine there ever be a use for such a type, and in current implementations, bool explicitly prohibits being subclassed.
The PEP 8 rule about using not using if cond is True: is specifically called out because it limits the value of cond to the bool only.
Last but not least, PEP 8 starts with this:
A Foolish Consistency is the Hobgoblin of Little Minds
[...] But most importantly: know when to be inconsistent -- sometimes the style guide just doesn't apply. When in doubt, use your best judgment. Look at other examples and decide what looks best.
Only follow PEP 8 if it suits your needs.
The second recommendation would best suit your needs. The conditional statement if cond: will return true if the condition itself is true. It will not change the behavior of the code, as it is just shorthand for if cond == True:.
I ran into unexpected results in a python if clause today:
import numpy
if numpy.allclose(6.0, 6.1, rtol=0, atol=0.5):
print 'close enough' # works as expected (prints message)
if numpy.allclose(6.0, 6.1, rtol=0, atol=0.5) is True:
print 'close enough' # does NOT work as expected (prints nothing)
After some poking around (i.e., this question, and in particular this answer), I understand the cause: the type returned by numpy.allclose() is numpy.bool_ rather than plain old bool, and apparently if foo = numpy.bool_(1), then if foo will evaluate to True while if foo is True will evaluate to False. This appears to be the work of the is operator.
My questions are: why does numpy have its own boolean type, and what is best practice in light of this situation? I can get away with writing if foo: to get expected behavior in the example above, but I like the more stringent if foo is True: because it excludes things like 2 and [2] from returning True, and sometimes the explicit type check is desirable.
You're doing something which is considered an anti-pattern. Quoting PEP 8:
Don't compare boolean values to True or False using ==.
Yes: if greeting:
No: if greeting == True:
Worse: if greeting is True:
The fact that numpy wasn't designed to facilitate your non-pythonic code isn't a bug in numpy. In fact, it's a perfect example of why your personal idiom is an anti-pattern.
As PEP 8 says, using is True is even worse than == True. Why? Because you're checking object identity: not only must the result be truthy in a boolean context (which is usually all you need), and equal to the boolean True value, it has to actually be the constant True. It's hard to imagine any situation in which this is what you want.
And you specifically don't want it here:
>>> np.True_ == True
True
>>> np.True_ is True
False
So, all you're doing is explicitly making your code incompatible with numpy, and various other C extension libraries (conceivably a pure-Python library could return a custom value that's equal to True, but I don't know of any that do so).
In your particular case, there is no reason to exclude 2 and [2]. If you read the docs for numpy.allclose, it clearly isn't going to return them. But consider some other function, like many of those in the standard library that just say they evaluate to true or to false. That means they're explicitly allowed to return one of their truthy arguments, and often will do so. Why would you want to consider that false?
Finally, why would numpy, or any other C extension library, define such bool-compatible-but-not-bool types?
In general, it's because they're wrapping a C int or a C++ bool or some other such type. In numpy's case, it's wrapping a value that may be stored in a fastest-machine-word type or a single byte (maybe even a single bit in some cases) as appropriate for performance, and your code doesn't have to care which, because all representations look the same, including being truthy and equal to the True constant.
why does numpy have its own boolean type
Space and speed. Numpy stores things in compact arrays; if it can fit a boolean into a single byte it'll try. You can't easily do this with Python objects, as you have to store references which slows calculations down significantly.
I can get away with writing if foo: to get expected behavior in the example above, but I like the more stringent if foo is True: because it excludes things like 2 and [2] from returning True, and sometimes the explicit type check is desirable.
Well, don't do that.
I am new the forum so hope this question is not too elementary or that it has been asked before. While writing some code in python, I found that individual functions (here called function1, function2 and function3) returning true or false would have the same output written to screen, and therefore I would like to link them together like this;
if function1 or function2 or function3:
print "something"
I know that function3 will take much more time to run, so I would like to avoid it. As the condition is now written it seems to me that it would be great for me if Python first evaluates function1 to false, and then stops the evaluation of the other conditions because it knows that the if-condition is already broken. The other possibility is that the returning values of all three functions are found separately before the truth value of the combined expression is evaluated. Does anybody know the sequences of action in the if condition-evaluation?
Python already does this for you with a mechanism known as "short-circuit" evaluation.
When a Boolean expression is found to be False (for an and) or True (for an or) at any stage during the evaluation, the rest of the expression is not evaluated since the end-result is already determined at that point.
So the order you put things into your Boolean expression really matters.
This is really quite useful since you can do something like this:
if i != 0 and 2332.0 / i:
...
to avoid division by zero with a simple and expression (i.e., the division will never take place if i is zero).
Also, note: You do need () for your function calls to work.
Finally, this short-circuiting evaluation isn't unique to Python, lots of languages do this.
What you're talking about is called "short-circuiting", and python does indeed do it.
However, I think if you want this to work properly, you want to use the and operator, not or as False or True returns True whereas False and True returns False (without ever looking at the second value). For completeness, True or False returns True (without ever looking at False).
Also, In your example, you're not actually calling the functions ... to call a function in python, you need parentheses:
function1(args) #for example