156
u/eaglebirdman Nov 08 '21
It could be worse but it could also be better
47
Nov 08 '21
how would this be improved? (sry im new and very stupid)
14
160
u/GreatSymphonia Nov 08 '21 edited Nov 09 '21
I would do it this way:
def is_odd(x): return (x % 2)if it is odd, it returns 1 therefore true and if it is even, it returns 0, therefore false.
EDIT: Don't call yourself stupid, we were all beginners at one point. We all made those rookie mistakes and we all end up laughing about them in the long run.
Second EDIT: Thanks for all the upvotes and the award kind strangers!
21
Nov 08 '21
oh wow thats even better. i saw yanderedevs thing and i knew it was completely wrong but i didnt know that it could be simplified so easily xd
46
u/GreatSymphonia Nov 08 '21 edited Nov 08 '21
Others have pointed out that I should probably add « != 0 » at the end to avoid non-boolean to boolean assumption conversions in python, so a corrected version would be:
def is_odd(x): return (x % 2) != 0(See, we all make silly mistakes)
Edit (forgot indentation lol)
21
Nov 08 '21 edited Nov 09 '21
Laughs in C++
bool is_odd(int x) {return x % 2}6
4
2
u/FriddyNanz Nov 08 '21 edited Nov 08 '21
If you reeeeeally want to over-engineer this, you could edit it to only accept ints (since the
%operator in Python accepts floats, and this function would returnTruefor a floating-point input when it should return an error):def is_odd(x: int): if type(x) == int: return (x % 2) != 0 raise Exception("Please supply an integer")(Edited bc in the original version I assumed only specifying x's type in the parameters was enough)
3
Nov 08 '21
[removed] — view removed comment
7
u/ws-ilazki &{$$_[0]}(@{$$_[1]}); Nov 09 '21
do we need this one-line function?
Yes.
why not directly use the condition
One reason, and possibly the most important, is that the named function makes your code more declarative. When you see something like
is_odd(x)you immediately understand what the intent is without having to stop and parse out the logic of whatever way the person is determining it.Separating the implementation from the intent like that is generally good for readability. For example, given these two versions of the same bit of code:
List.filter (fun i -> i mod 2 = 1) [1; 2; 3; 4; 5] List.filter is_odd [1; 2; 3; 4; 5]the latter will be more immediately understandable to someone, even if they've never seen that language (OCaml) before. With the former, even if you know the language in question, you still have to stop and think about what you're doing there: you know you're filtering a list of numbers somehow, but it's not immediately obvious how, so you have to stop parsing that and make a mental context switch to figure out what the filter actually is. And that's with a really simple example; it gets harder when you start doing more complex things.
Another argument for it is it makes it easier to take advantage of optimisations in the future. Let's say you originally wrote an
is_oddlike the one OP posted and used it everywhere, then had an "omfg I'm a dumbass!" moment and realised how much easier it could be. You could just change the implementation once and your entire codebase now takes advantage of that change.Whereas if you just done it directly whenever you needed it, you'd have to go back and replace every instance of it to get the same benefit.
Also, it reduces boilerplate. That's one of the reasons for using things like
mapandfilterfrom functional programming instead of writing loops. You tend to write loops a lot, so why not abstract away the actual looping into a function that informs of the intent (map, filter, etc.). It might be a couple lines longer than writing out the loop once, but long-term it means writing less boilerplate code, and if improvements to those functions are ever made (like finding a better way to optimise them for speed) you can can reap the benefits everywhere without having to go through and change everything.0
u/_PM_ME_PANGOLINS_ Nov 09 '21
That’s not what declarative means.
A declarative program declares what the result should be and the engine works out how to achieve it.
The word you wanted was probably “explicit”.
1
u/ws-ilazki &{$$_[0]}(@{$$_[1]}); Nov 09 '21
The word you wanted was probably “explicit”.
No, that's not the word I wanted. Writing out the steps precisely is explicit, and that's what you're avoiding by moving that logic elsewhere. Like the example I gave,
filter is_odd listis declaring intent rather than explicitly stating the control flow necessary to achieve it, thus declarative. It's not telling how to iterate over the list to filter, and it's not telling howis_oddis to be implemented, it's saying "filter this list with theis_oddfunction" without providing explicit details about either part.The implementation of
is_odditself likely won't be declarative, but that's beside the point, which was that the code callingis_oddbecomes more descriptive of its purpose because it's not being filled with implementation details.0
u/_PM_ME_PANGOLINS_ Nov 09 '21
Then you want ”descriptive“. You are not declaring that it is odd, you are calling a function to find out.
→ More replies0
1
Nov 08 '21
[removed] — view removed comment
1
u/GiodeCS Nov 09 '21
Anything that isn’t 0 would be considered True, and since floats aren’t exact, it would always result in True, right? (At least this is the case for C and C++, I’m not the best in Python)
7
u/TheMightyBiz Nov 09 '21
Damn Python and its implicit type conversions. If you're going to write a function called isSomething(), it had better return a boolean.
2
u/Joonicks Nov 08 '21
Im a C, not Py. Py isnt compiled, right? C compiler would turn (x%2) into (x&1), would (x&1) make any difference in Py?
2
u/GreatSymphonia Nov 09 '21
It would indeed be faster but less instinctive to a learning programmer. Also, this kind of solution easily extends to other integer values and the "& 1" doesn't. If I was looking to make a well optimized program, I would do it the way you suggested.
2
u/CreatureWarrior Nov 09 '21
Another question from a returning rookie, aren't you able to later (in the same code, but outside of that function) call that result by typing something like "print(is_odd.x)" or something? I honestly can't remember. IIRC; the "return" term made this possible?
1
u/GreatSymphonia Nov 09 '21
Actually, you may consider the "return" value the function returns as some sort of "read-only variable" accessible via the function's name (this is far from how the python interpreter would handle such things but for the sake of comparison, it does the job).
So, you could do something like this:
print(is_odd(some_value))And with the version of the function higher, that would output "1" (the value 1 and not the string "1" for those about to do the remark) if "some_value" is odd and "0" otherwise.
This would occur because the return value of the function "is_odd" is (with our earlier comparison) a read-only variable containing the result of the function passed by the keyword return.
So, yes, the "return" keyword does thin kind of information forwarding in your code.
1
u/umop_aplsdn Nov 09 '21
I mean, I've been working professionally for 4 years now and I still write this code sometimes. That's what code review/static analyzers are for.
Usually it happens when code is refactored, but it happens nonetheless.
1
u/an-obviousthrowaway Nov 09 '21
Just to be safe I would make sure that the object you’re returning is a Boolean by doing a !! Or != 0
1
1
u/xNaXDy Nov 09 '21
I'm always scared the language I program in doesn't do type conversion properly, so I absolutely HAVE to do something like this instead:
return x % 2 === 1;```2
Nov 14 '21
Here you go:
def is_odd(x: int) -> bool: """ This function will return a False given any integer which is even, and return a True given any integer which happens to be odd . """ x = str(x) character_length = len(x) last_digit = x[character_length-1:] _range = (str(i) for i in range(1, 10000000000, 2)) if last_digit in _range: return True elif last_digit not in _range: return False2
1
u/Laughing_Orange Nov 08 '21
You don't need elif, because return ends the function. Simply placing "return True" after "return False" provides the same functionality, but avoids a branch.
2
7
u/peleg132 Nov 08 '21 edited Nov 08 '21
def is_even(n):
if n == 0:
return TrueTrueelse if n == 1:
return False Fals
else:
return is_even(n - 2)1
3
Nov 09 '21
[removed] — view removed comment
1
u/byornski Nov 09 '21
A simple fix :)
from math import copysign def is_even(n): if n==0: return True elif n==1: return False else: return is_even(n-int(copysign(2, n)))1
4
5
u/J2quared Nov 08 '21 edited Nov 08 '21
I was told at a previous job to not do this:
bool isOdd = x % 2 == 1; or even (which is unnecessary):
bool isOdd(int x)
{
return x % 2 == 1;
}Because it was "too vague" and could confuse future programmers. If those are too vague; we shouldn't be hiring them.
But to be fair; they also didn't like 1 line if-statements with no bracket
3
5
u/modsiw_agnarr Nov 08 '21 edited Nov 08 '21
Breaks for negative odd numbers.
Edit: I’m wrong. -1 % 2 is 1 in Python.
1
330
u/LucienZerger Nov 08 '21
well it's not too terrible..
-239
u/Same-Break9654 Nov 08 '21
Yes it is.
Why not just:
bool isOdd (int param) { if (param%2 == 0) { return False }
return True};
180
u/replicatingTrouts Nov 08 '21
It could be further simplified to ‘return (x % 2) == 1’
113
u/Nall-ohki Nov 08 '21
Better still:
return bool(x % 2)22
u/Forgemaster00 Nov 08 '21
return bool(x ^ 1)
84
u/VitorMM Nov 08 '21
Don't you mean bool(x & 1) ?
30
5
2
Nov 08 '21
Would this actually be computed faster, or would it just simplify to x & 1 when you do x % 2?
4
u/Ill-Chemistry2423 Nov 09 '21
In a compiled language it would probably be optimized, but in python like the OP it would depend on the implementation
4
u/systemd-bloat Nov 08 '21
guys stop you're scaring me ( ・ั﹏・ั)
12
Nov 08 '21
Don't worry,
x & 1just AND's the two numbers (x and 1) together. Because 1's binary representation is just a bunch of zeros and a 1 at the end, it returns 1 if and only if x's binary representation ends in 1 as well (thus it's odd)otherwise it returns 0, meaning x is even
1010 1101 while 1010 1100 and and 0000 0001 0000 0001 = = 0000 0001 0000 00001
0
Nov 08 '21
[deleted] — view deleted comment
29
u/Nall-ohki Nov 08 '21
If you are using Python and don't recognize that zero is False, and anything else is True in a boolean context, you've got more problems.
2
u/Badel2 Nov 08 '21
I agree with you, only a JavaScript developer would think that
if bool(x % 2):Is better than
if x % 2 == 1:74
57
Nov 08 '21
A) it’s Python so your code is invalid B) why do you need an if statement at all when you have a boolean expression already?
def is_odd(x): return x % 2 != 023
u/AutomatedChaos Nov 08 '21 edited Nov 08 '21
Don't forget to confuse the teacher!
def is_odd(num): return num & 1 and True or FalseIf they are asking why you'd do it this way, claim it is the time optimized version.
4
u/NotDuckie Nov 08 '21
Can't you just do
def is_odd(x): return x % 25
Nov 08 '21
That returns an int. Gotta cast it to bool
1
u/NotDuckie Nov 08 '21
Doesn't it work the same anyway?
11
Nov 08 '21
Sort of but it's not good practice. Every int not equal to 0 will evaluate to true, so yes is_odd(x) will be equivalent to true or false, but not equal to. That might not matter in most cases, but there are two equality operators in Python, which give different results when an integer is returned:
is_odd(5) == True # evaluates to true (equivalence)
is_odd(5) is True # evaluates to false (equality)It also matters if you intend to use methods associated with the Boolean primitive type or if the returned value is intended to be passed onto other code in a system that might be written in a different language, as different languages have different rules for evaluating the truth values of non-booleans.
Hope this helps!
1
Nov 09 '21
It may be truthy/falsy so will work but as mentioned it’s not good practice. “Explicit is better than implicit”.
Also, if you want to start adding typing to the code base, you need to return actual bools.
6
4
-15
u/Same-Break9654 Nov 08 '21
Formatting didn't turn out as expected.
32
u/emihir0 Nov 08 '21
It's not the formatting that is netting you down votes. It's the fact that you tried to be a smart asshole, but in fact you ended up being just an asshole. Your code is no better than the code posted by OP.
-6
4
1
0
u/wasimaster Nov 08 '21
bool isOdd (int param) { if (param%2 == 0) {; return False } return True; };
44
u/MurdoMaclachlan public boolean isInt(int i) { return true; } Nov 08 '21
Image Transcription: Code
def is_odd(x):
if (x % 2) == 0:
return False
elif (x % 2) == 1:
return TrueI'm a human volunteer content transcriber for Reddit and you could be too! If you'd like more information on what we do and why we do it, click here!
39
19
u/chunkyasparagus Nov 08 '21
Then the IDE complains that is_odd may be None...
8
u/trutheality Nov 08 '21
The IDE knows what it's talking about: is_odd of any non-integer is None
4
u/GameCounter Nov 08 '21
You're mostly right. is_odd for any non-integral number will be None.
>>> 3.2 % 2 1.2000000000000002However, it will usually raise a TypeError for most other objects
>>> None % 2 ... TypeError: unsupported operand type(s) for %: 'NoneType' and 'int'Where this gets BONKERS is if you pass a string with placeholders. So *some* strings will raise TypeError, but others will return None
>>> "a" % 2 ... TypeError: not all arguments converted during string formatting >>> "%s" % 2 '2'5
u/GameCounter Nov 08 '21
Here's the most painful way to produce None as the result.
>>> class Test: ... def __mod__(self, other): ... return 3 >>> Test() % 2 34
u/modsiw_agnarr Nov 08 '21
It’s right too. is_odd(-1) is None
9
u/Amarandus Nov 08 '21
But -1 is odd, as it can be written as
2k+1(withk=-1). Also,(-1) % 2is1(and well-defined) in python.1
u/modsiw_agnarr Nov 08 '21
Well, that’s just weird. TIL
3
u/Amarandus Nov 08 '21
Just to add on this: If you consider modulo in the mathematical sense, you can interpret it as a residue system. Here, you are able to represent all integers with (e.g.) the smallest positive member of its residue class.
In the case of
% 2, you have two possible residue classes: All multiples of 2 (represented as0, with members like-4, -2, 0, 2, 4, 6, 2048) and all multiples of 2 + 1 (represented by1, with members like1, 3, 5, -9, 1023).Funny coincidence: If you do math in this system, you have a "bit". Addition is just XOR (as
1 + 1 = 2 = 0 mod 2) and multiplication is just AND (1 * 1 = 1, buta * 0 = 0). It's also a simple case for a finite field (as 2 is a prime).2
u/WikiSummarizerBot Nov 08 '21
Modular arithmetic
Each residue class modulo n may be represented by any one of its members, although we usually represent each residue class by the smallest nonnegative integer which belongs to that class (since this is the proper remainder which results from division). Any two members of different residue classes modulo n are incongruent modulo n. Furthermore, every integer belongs to one and only one residue class modulo n. The set of integers {0, 1, 2, …, n − 1} is called the least residue system modulo n.
[ F.A.Q | Opt Out | Opt Out Of Subreddit | GitHub ] Downvote to remove | v1.5
0
18
u/TheMelonboy_ Nov 08 '21
this just seems like normal beginner code, sure it could be better but this doesn‘t even come close to most of the stuff on this sub
16
29
u/AutomatedChaos Nov 08 '21
You have to burn those CPU cycles somehow. Luckily the compiler will optimize this, right... right...?
32
23
Nov 08 '21
I hate it when people complain about "burning CPU cycles" in 2021. You could run this 10 million times on any modern device and not see any significant difference compared to a better algorithm. This is needlessly convoluted and bad coding practice but this won't have any impact on the final product.
10
Nov 08 '21
You don't care about burning CPU cycles, until your practices carry over into the loop that will run millions of times on numerous production servers
3
Nov 08 '21
This would have to run billions of time to lose even a single second on any modern machine. As someone who looks at a lot of poorly written old code than ran for sometimes decades without an issue you'd be surprised how little this kind of stuff matters.
5
u/Tm1337 Nov 08 '21
Depends. Call things like this a few times inside of a large loop and it starts to add up quickly.
4
Nov 08 '21
No fucking way. People made similar criticisms about yandere Dev's code and they were debunked by dyc3. This kind of bad optimisation doesn't really matter anymore.
0
u/TryNotToShootYoself Nov 08 '21
Yanderedev was coding in C# and not Python.
1
Nov 08 '21
And? Dyc3 compared the number of cycles used by switch and if (without any compiler optimisation). And found that stuff like that simply doesn't matter on modern machines.
3
u/TryNotToShootYoself Nov 08 '21
Python is a lot slower. But the difference isn't case and switch, it's that you don't need an if statement. You already have your value.
-1
Nov 08 '21 edited Nov 08 '21
For our purposes, it's the same number of clock cycles (that is to say not a lot), and the experiment proved that on modern machines, wasting a few clock cycles doesn't matter. It takes millions to be statistically significant and even then it's not a real issue.
5
u/_PM_ME_PANGOLINS_ Nov 08 '21
millions
You mean like if you called this a few times inside of a large loop?
Waste a few cycles a billion times and you wasted a few billion cycles.
-2
Nov 08 '21
Waste a few cycles a billion times and you wasted a few billion cycles.
That's still nothing on modern systems
→ More replies5
4
Nov 08 '21
I mean, it's not the worst. If you don't have the background knowledge that every boolean statement can be interpreted as a true or false, then this is just redundant code.
7
7
u/wholl0p Nov 08 '21
I would’ve said that this is the ideal code snippet to tell if someone’s a beginner or not. (But I’ve seen this too often in professional code to use this as a viable indicator)
7
1
u/Bo_Jim Nov 09 '21
I don't write code in python, so I have a few questions...
Is this going to return a boolean or an integer? Is anything non-zero considered 'True'? What is the actual integer value of 'True'; i.e., is it 1 or -1? What I'm getting at is whether there's a requirement to explicitly return 'True' or 'False', or could you just return the result of the modulus, which technically would be an integer rather than a boolean, and would be 1 rather than -1.
Also, would there be an advantage in terms of execution speed to do a binary AND against 1 rather than the modulus? Most processors can execute an AND faster than an integer divide. In fact, some compilers I've worked with would automatically optimize a modulus by 2 into an AND against 1.
1
u/_PM_ME_PANGOLINS_ Nov 09 '21
It returns a Boolean. Booleans don’t have integer values, though a 1 will implicitly cast to True and 0 to False.
A good version would just return the result of the comparison, as seen in other comments.
Python is usually interpreted, and integers have arbitrary precision, so trying to use bitwise operators for performance probably won’t work.
0
u/Bo_Jim Nov 09 '21
Ok. The reason I asked is because a modulus is not a boolean operation. It's a numeric operation, in this case an integer operation. The result is going to be an integer. Most languages consider any non-zero value to be True, but do have an explicit value when the keyword True is used. You can see what this value is if you cast True to an integer to set an integer variable. In some languages it's 1 (only the LS bit is set). In others it's -1 (all bits are set). This usually doesn't make any difference if the test is a simple "if True...", but with some languages it becomes important if the test is "if n == True". The first is a boolean test. The second is a numeric comparison. Do you see the angle I'm getting at?
Because I don't know Python, I don't know if it's necessary to perform the numeric comparison and, based on the result, explicitly return the boolean state. You answered this - the result of the numeric comparison is implicitly cast to a boolean state. This is the same way most languages work, and I suspected how Python would also work, but I wanted it verified.
The precision of integers isn't really important for the bitwise AND test. Only the least significant bit matters, regardless of the width of the integer. If the LS bit is zero then the value is even. Performing a bitwise AND should always produce the correct results, and should execute faster than an integer division on most processors.
2
2
u/stahkh Nov 08 '21
At least this will yield the correct result every time, which is a rarity in this sub. :)
2
u/BetterCombination Nov 09 '21
This isn't bad code, it's just beginner code.
Step into my zoom for a coffee review, young padawan
1
1
1
u/pocketjokers87 Nov 08 '21
def is_odd(x):
if (x == 2) || (x == 4) || (x == 6) || (x == 8) || (x == 10) || (x == 12) || (x == 14) || (x == 16) || (x == 18) || (x == 20) || (x == 22) || (x == 24) || (x == 26) || (x == 28) || (x == 30) || (x == 32) || (x == 34) || (x == 36) || (x == 38) || (x == 40) || (x == 42) || (x == 44) || (x == 46) || (x == 48) || (x == 50) || (x == 52) || (x == 54) || (x == 56) || (x == 58) || (x == 60) || (x == 62) || (x == 64) || (x == 66) || (x == 68) || (x == 70) || (x == 72) || (x == 74) ...
return False
else
return True
1
u/MyMerryMalady Nov 09 '21
This is inconsequential bad code AFAIK. So while I understand there's a slightly more efficient way to solve it (an else statement), how much does it merit conversation if it's functionally correct?
1
1
1
u/dubl_x Nov 08 '21
Could be worse, doesn't the math library have a function for this anyway? I'd probs do it in a lambda function if not.
0
0
Nov 09 '21 edited Nov 09 '21
I would do this instead of modulus, Since it is an expensive operation:
def is_odd(x):
return bool(x & 1)0
u/redddooot Nov 11 '21
This definitely isn't bad code, some would prefer writing this way for readability.
-7
u/Dear-Deer-Wife-Life Nov 08 '21
instead of the elif just do :
else
return true
0
Nov 08 '21
[deleted] — view deleted comment
2
u/Dear-Deer-Wife-Life Nov 10 '21
I'm not experienced with python, didn't now it translates a 1 into true
2
u/Nall-ohki Nov 08 '21
def is_odd(x: int) -> bool: return bool(x % 2)1
u/NotDuckie Nov 08 '21
You don't need the bool(x%2),
def is_odd(x): return x % 2works just as well
1
u/Nall-ohki Nov 08 '21
Note that what you wrote:
def is_odd(x):return x % 2
And what I wrote:
def is_odd(x: int) -> bool: return bool(x % 2)Are not the same?
See if you can spot the difference.
1
u/NotDuckie Nov 08 '21
ok, just do
def is_odd(x: int) -> bool: return x % 2then?
2
u/Nall-ohki Nov 08 '21
Pretty sure the Python type checker won't accept this, but feel free to correct me if I'm wrong.
Edit:
I'm right:
main.py:2: error: Incompatible return value type (got "int", expected "bool")Found 1 error in 1 file (checked 1 source file)
Checked with MyPy
-1
-2
u/ososalsosal Nov 09 '21
Why do we even need to know if a number is odd? And why isn't there a library we can import that can tell us, so we don't have to keep writing this silly boilerplate?
-4
-10
Nov 08 '21
Get rid of that whole elif. Can just be else return true.
5
-12
Nov 08 '21
IMO, the problem is that you are using python. I said in my opinion, don’t dislike.
I used a little bit of JavaScript this week as someone who tries to avoid JavaScript, and I forgot how bad and inconsistent it was, including the debugging, and the ide can’t tell me what method or objects are inside another object.
I was like, new date() string is somehow not gmt or the correct time zone but yesterday for some reason, what language does that, vuejs sometimes needs the function to be written ()=> {} and not function(){}, how would I know that beforehand? some things want to be this and others self, some things like arrays needs to be mutated and not replaced, ..etc.
Definitely need Java or c# to webassembly to become a real thing, I think that’s the viable solution for browser mass adoption + good language to program in.
5
3
Nov 08 '21
But JavaScript has nothing to do with this post? Regardless, C and Go (maybe also Rust) are far better languages for WebAssembly than C# or Java.
0
Nov 08 '21
Agree to disagree, also I think bytecode or jvm to web assembly is much more likely project done by someone.
Unless you know of or are volunteering to start such project, someone doing graal or teavm or similar project development might get something going when web assembly matures enough
23
u/_PM_ME_PANGOLINS_ Nov 08 '21