?

Log in

No account? Create an account
   Journal    Friends    Archive    Profile    Memories
 

Python boolean function danger - morfizm


Jun. 12th, 2012 02:52 pm Python boolean function danger

class number(int):
    def is_odd(self):
        return self % 2 == 1

>>> if number(5).is_odd(): print '5 is odd'
...
5 is odd

>>> if number(6).is_odd(): print '6 is odd'
...

>>> if number(5).is_odd: print '5 is odd'
...
5 is odd

>>> if number(6).is_odd: print '6 is odd'
...
6 is odd


Upd.: got a good solution. Use properties:

class number(int):
    @property
    def is_odd(self):
        return self % 2 == 1

print number(6).is_odd
print number(6).is_odd()

the latter call will produce
TypeError: 'bool' object is not callable

24 commentsPrevious Entry Share Next Entry

Comments:

From:dennyrolling
Date:June 12th, 2012 09:58 pm (UTC)
(Link)
oh this is my favorite piece of code:
If Odd(5) Then WriteLn('5 is odd.') Else WriteLn('This is odd.');
(Frozen) (Thread)
From:morfizm
Date:June 12th, 2012 10:04 pm (UTC)
(Link)
Yeah, I adore it too. I think it was from Borland Pascal help.
(Frozen) (Parent) (Thread)
From:kot_begemot
Date:June 12th, 2012 10:21 pm (UTC)
(Link)
Ну вообще говоря Питон тут не уникален.
Т.е. любой язык (и в частности C и все его производные, включая сюда и Жабу), в котором существуют во-первых указатели на функции, во-вторых неявное преобразование указателей в boolean, будет страдать тем же самым.
(Frozen) (Thread)
From:morfizm
Date:June 12th, 2012 10:26 pm (UTC)
(Link)
C++ will spit a warning. /Wall /WX and the code will break.
(Frozen) (Parent) (Thread)
From:kot_begemot
Date:June 13th, 2012 12:36 am (UTC)
(Link)
Это какой же именно warning?
(Frozen) (Parent) (Thread)
From:morfizm
Date:June 13th, 2012 01:09 am (UTC)
(Link)
MSFT: warning C4551: function call missing argument list
gcc: warning: the address of `bool f()', will always evaluate as `true'

Edited at 2012-06-13 01:28 am (UTC)
(Frozen) (Parent) (Thread)
From:raindog_2
Date:June 12th, 2012 10:22 pm (UTC)
(Link)
This can happen in many popular languages, Python is not special in any way here.

E.g., in C++:

#include

bool f() { return false; }

int main() {
if (f) std::cout << "Here you go\n";
return 0;
}
(Frozen) (Thread)
From:morfizm
Date:June 12th, 2012 10:25 pm (UTC)
(Link)
В C++ ты получишь warning когда pointer неявно кастится в bool.
(Frozen) (Parent) (Thread)
From:raindog_2
Date:June 12th, 2012 10:53 pm (UTC)
(Link)
No, I don't think it's true for C++ in general. Some compilers might give you a warning, but I think it's a completely legit C++ construct.
At least, gcc shouldn't complain.
(Frozen) (Parent) (Thread)
From:morfizm
Date:June 13th, 2012 01:10 am (UTC)
(Link)
C++ language is not ideal, it has many stupid constructs that do not generate warnings when they should. So legitimity of the construct in language is not a strong argument here.

MSFT's compiler gives this:
warning C4551: function call missing argument list

Upd:
gcc: warning: the address of `bool f()', will always evaluate as `true'

Edited at 2012-06-13 01:29 am (UTC)
(Frozen) (Parent) (Thread)
From:raindog_2
Date:June 13th, 2012 01:33 am (UTC)
(Link)
The warning doesn't make any sense to me. We are using the function address, and not calling in. Are you sure you compiled exactly my example? If so, the compiler is just wrong here.

But then, how do you take the address of a function??? Normally it would be like this:
bool (*p)() = f;
Would the MSFT comiler complain about this one too?
(Frozen) (Parent) (Thread)
From:morfizm
Date:June 13th, 2012 01:48 am (UTC)
(Link)
MSFT compiler will not complain about this.

I think you approach is too theoretical. Your reasoning shows that you want warnings to be consistent throughout "valid" language construct. E.g. if we have a feature "compiler can cast various types automatically to bool" and a feature "we can take address of a function", then it feels like you kinda assume you can always combine them. It's not the case, and, in my opinion, should not be the case. There are combinations which are dangerous, and I am totally fine with the fact that MSFT compiler doesn't want to treat function name as a pointer when it should be cast to bool, but instead expects a pointer type conversion.

bool (*p)() = f;

Doesn't give a warning.
(Frozen) (Parent) (Thread)
From:raindog_2
Date:June 13th, 2012 03:48 am (UTC)
(Link)
Да, в-общем, ты прав. На то они и warningи. Это меня что-то перемкнуло. Я только вернулся из бурного отпуска в Украине/Германии/Италии/Франции, не отошел еще от перелета :)
(Frozen) (Parent) (Thread)
From:raindog_2
Date:June 13th, 2012 01:34 am (UTC)
(Link)
Your gcc warning has nothing to do with the question we discuss.
(Frozen) (Parent) (Thread)
From:morfizm
Date:June 13th, 2012 01:50 am (UTC)
(Link)
Disagree.
The question we discuss: whether usage of dangerous patterns should be flagged by compiler. In this case GCC does flag it, so it's a supporting argument in my case.

I can easily imagine a conversation among GCC developers like "should we implement a warning when you're trying to use function pointer where bool is expected?" -- "no, why? we already have a warning about constant expression."
(Frozen) (Parent) (Thread)
From:raindog_2
Date:June 13th, 2012 02:00 am (UTC)
(Link)
Yes, agreed. My first reaction was like that because it has nothing to do with usage of pointers in if(). I.e. something like void *p = ...; if(p) should be valid in any compiler, I believe.
(Frozen) (Parent) (Thread)
From:raindog_2
Date:June 13th, 2012 01:51 am (UTC)
(Link)
Well, I take it back. It actually has something to do, but it gets more complicated.
1) You can declare a class with a static function and then the gcc doesn't complain at all (probably because it can't find the address of the member function in compile time).
2) However, if that's a non-static member function, you can't just use it as an address, so you can't make a mistake.
(Frozen) (Parent) (Thread)
From:morfizm
Date:June 13th, 2012 01:56 am (UTC)
(Link)
1) You can declare a class with a static function and then the gcc doesn't complain at all (probably because it can't find the address of the member function in compile time).

Please give me a code snippet.
I've just tried it and still got a warning:

warning: the address of `static bool A::f()', will always evaluate as `true'
(Frozen) (Parent) (Thread)
From:raindog_2
Date:June 13th, 2012 02:02 am (UTC)
(Link)
struct C { static bool f() { return true; } };

if (C::f) ...
(Frozen) (Parent) (Thread)
From:raindog_2
Date:June 13th, 2012 02:04 am (UTC)
(Link)
gcc version 4.4.3
comipiles with -Wall
(Frozen) (Parent) (Thread)
From:morfizm
Date:June 13th, 2012 02:14 am (UTC)
(Link)
Hm...

warning: the address of `static bool C::f()', will always evaluate as `true'

gcc version 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
-Wall -Werror

On the other hand, the other version gives no warnings:

gcc version 4.4.6 20110731 (Red Hat 4.4.6-3) (GCC)
(Frozen) (Parent) (Thread)
From:dennyrolling
Date:June 13th, 2012 12:18 am (UTC)
(Link)
какой такой warning ты получишь?
(Frozen) (Parent) (Thread)
From:morfizm
Date:June 13th, 2012 01:09 am (UTC)
(Link)
MSFT: warning C4551: function call missing argument list
gcc: warning: the address of `bool f()', will always evaluate as `true'

Edited at 2012-06-13 01:29 am (UTC)
(Frozen) (Parent) (Thread)
From:dennyrolling
Date:June 13th, 2012 07:36 am (UTC)
(Link)
http://codepad.org/bXdLbYFz

возвращает 2, компилируется с -Wall -Wextra без предупреждений на gcc 4.4.3

Edited at 2012-06-13 07:40 am (UTC)
(Frozen) (Parent) (Thread)