67

Here is my custom class that I have that represents a triangle. I'm trying to write code that checks to see if self.a, self.b, and self.c are greater than 0, which would mean that I have Angle, Angle, Angle.

Below you will see the code that checks for A and B, however when I use just self.a != 0 then it works fine. I believe I'm not using & correctly. Any ideas? Here is how I am calling it: print myTri.detType()

class Triangle:

    # Angle A To Angle C Connects Side F
    # Angle C to Angle B Connects Side D
    # Angle B to Angle A Connects Side E

    def __init__(self, a, b, c, d, e, f):
        self.a = a
        self.b = b
        self.c = c
        self.d = d
        self.e = e
        self.f = f

    def detType(self):
        #Triangle Type AAA
        if self.a != 0 & self.b != 0:
            return self.a

        #If self.a > 10:
            #return AAA

        #Triangle Type AAS

        #elif self.a = 0:
            #return AAS

        #Triangle Type ASA

        #Triangle Type SAS

        #Triangle Type SSS  

        #else:
            #return unknown
Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
Noah Clark
  • 8,101
  • 14
  • 74
  • 116

3 Answers3

131

You should write :

if (self.a != 0) and (self.b != 0) :

"&" is the bit wise operator and does not suit for boolean operations. The equivalent of "&&" is "and" in Python.

A shorter way to check what you want is to use the "in" operator :

if 0 not in (self.a, self.b) :

You can check if anything is part of a an iterable with "in", it works for :

  • Tuples. I.E : "foo" in ("foo", 1, c, etc) will return true
  • Lists. I.E : "foo" in ["foo", 1, c, etc] will return true
  • Strings. I.E : "a" in "ago" will return true
  • Dict. I.E : "foo" in {"foo" : "bar"} will return true

As an answer to the comments :

Yes, using "in" is slower since you are creating an Tuple object, but really performances are not an issue here, plus readability matters a lot in Python.

For the triangle check, it's easier to read :

0 not in (self.a, self.b, self.c)

Than

(self.a != 0) and (self.b != 0) and (self.c != 0) 

It's easier to refactor too.

Of course, in this example, it really is not that important, it's very simple snippet. But this style leads to a Pythonic code, which leads to a happier programmer (and losing weight, improving sex life, etc.) on big programs.

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
Bite code
  • 578,959
  • 113
  • 301
  • 329
  • 8
    Why is "if 0 not in (self.a, self.b):" shorter? Is that really idiomatic python? Yes it's shorter by a few characters, but probably slower. You have to construct a tuple and it just looks awkward. – Tom Jul 02 '09 at 17:38
  • 11
    Speed on such a little bunch of data is not an issue. Anyway, readabilty is often more important that speed in Python. In it's case, it's very useful because if you want to check the 3 angles, it's cleaner to write it this way than with 3 "and". – Bite code Jul 02 '09 at 17:47
  • 6
    Usually use that when the left hand side is variable, like: if x in (2, 3, 5, 7) ... – FogleBird Jul 02 '09 at 18:06
  • 3
    I'm not going to argue, I am just going to say as a matter of personal taste, I think that is less pythonic. I'm more inclined to agree with FogleBird. Regardless... it is correct :-). – Tom Jul 02 '09 at 18:11
  • I actually compared 'in' performance to boolean operators recently, and there are cases where 'in' wins: http://www.heikkitoivonen.net/blog/2009/06/16/remember-your-in-operator/ – Heikki Toivonen Jul 02 '09 at 18:16
  • "if (self.a != 0) and (self.b != 0):" : Aarrgghh! It's not Pascal! First refinement: "if self.a != 0 and self.b != 0"; second refinement "if self.a and self.b:" – John Machin Jul 02 '09 at 23:36
  • 4
    @Heikki: If the tuple is a *CONSTANT* e.g. "a in (1, 7, 15)" then it's got a chance of being faster because the tuple is evaluated at compile-time; however in a case like the OP's 0 in (vbl0, vbl1, vbl2) it's unlikely to be faster and looks fugly. – John Machin Jul 02 '09 at 23:48
  • 1
    @John. Nope. We are dealing with maths. We want 0 to ba taken in consideration, but not "false". You can't remove !=. – Bite code Jul 03 '09 at 04:54
  • 1
    @e-satis: not Nope. Yes we are dealing with maths, specifically the sides and angles of a triangle which are floats (or ints) ... under the condition that there aren't any strings or None or other rubbish, `if x` means exactly the same as `if x != 0`. If you are worried about rubbish, that should be checked right up front before you start checking multi-attribute conditions. – John Machin Jul 03 '09 at 09:38
  • That would mean type checking, which is something we don't want in Python. We don't want to put setters neither. I think using the tuple approach is a good win-win deal taking in consideration that "python is not pascal" but witouth overloading the code with checks. – Bite code Jul 03 '09 at 11:06
  • @e-satis: Your tuple doesn't help you. 0 not in (rubbish1, rubbish2) ... rubbish1 != 0 and rubbish2 != 0 ... rubbish1 and rubbish2 ... the answers are ALL rubbish. If there's no rubbish, the three forms are equivalent. – John Machin Jul 03 '09 at 12:27
  • You don't need to be rude, mate. – Bite code Jul 03 '09 at 13:01
  • 1
    @e-satis: Correct, and I'm not being rude. I'm using "rubbish" in the same sense as "garbage" in "GIGO" (garbage in, garbage out). Garbage in being strings, None, etc. Garbage out being meaningless results. I wasn't advocating type checking and/or setters, either. How would you feel about doing `self.a = float(a)` instead of `self.a = a` in the __init__ method? – John Machin Jul 03 '09 at 23:54
  • It's surely clean. Anyway, I'm not sure a 20 char long condition statement deserved to be debated so much :-) – Bite code Jul 04 '09 at 11:38
  • 1
    Can we all just agree that using `in` is horrible style and not more readable? This sort of code golf leaves a DRY feeling in my mouth. – bug Jan 27 '14 at 18:27
  • ``But this style leads to a Pythonic code, which leads to a happier programmer (and losing weight, improving sex life, etc.) on big programs.'' The answer has made my day. – beahacker Jun 22 '17 at 06:26
23

Use the keyword and, not & because & is a bit operator.

Be careful with this... just so you know, in Java and C++, the & operator is ALSO a bit operator. The correct way to do a boolean comparison in those languages is &&. Similarly | is a bit operator, and || is a boolean operator. In Python and and or are used for boolean comparisons.

Melebius
  • 6,183
  • 4
  • 39
  • 52
Tom
  • 21,468
  • 6
  • 39
  • 44
  • 9
    You can also use `and` in lieu of `&&` in _standard_ (i.e., non-Microsoft;-) C++. – Alex Martelli Jul 03 '09 at 02:34
  • 4
    wow! I really had no idea you could do that, Alex. I asked some of my very C++ savvy friends and they didn't know either! Also it's not easy to find online. But sure enough, I tried it and it worked :-). Thanks! – Tom Jul 04 '09 at 05:56
14

It's called and and or in Python.

Trenton
  • 11,678
  • 10
  • 56
  • 60
Lennart Regebro
  • 167,292
  • 41
  • 224
  • 251