views:

896

answers:

3

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
+7  A: 

Use the keyword "and", not &. & 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.

Tom
You can also use `and` in lieu of `-) C++.
Alex Martelli
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
A: 

It's called "and" and "or" in Python.

Lennart Regebro
+7  A: 

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 O 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 :

O not in (self.a, self.b, self.b)

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 loosing weight, improving sex life, etc) on big programs.

e-satis
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
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".
e-satis
Usually use that when the left hand side is variable, like: if x in (2, 3, 5, 7) ...
FogleBird
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
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
"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
@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
@John. Nope. We are dealing with maths. We want 0 to ba taken in consideration, but not "false". You can't remove !=.
e-satis
@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
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.
e-satis
@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
You don't need to be rude, mate.
e-satis
@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
It's surely clean. Anyway, I'm not sure a 20 char long condition statement deserved to be debated so much :-)
e-satis