Hacker News new | ask | show | jobs
by jamespwilliams 1992 days ago
Looks cool.

    bool (__bool__) Returns whether all elements evaluate to True.
I’d be worried that this will trip people up who use the

    if l:
        print l[0] # or whatever
pattern
2 comments

To be fair, using "if something" in Python is pretty much always a good way to trip yourself up.
I've yet to see a (popular) style guide recommend against "if something:".
I don't really see how this is a reason not to carefully consider the type of an object when using truthiness.
PEP8 recommends using `if seq:` instead of more verbose alternatives like `if len(seq):`.
If you know that "something" is a sequence, then is the idiomatic thing to do. The point is that any time you rely on truthiness of a value, you need to think (sometimes quite carefully) about what type of value you're dealing with.
For good reason - len(something) or alternatives might be expensive to compute, bool(something) is actually what you are trying to do and can be optimised depending on the container.
For the basic sequence types (list, tuple, and range), len is definitely not expensive to compute. For custom types, it will depend on your implementation of __len__ (but then, computation of bool(...) will also depend on your implementation of __bool__).
Yes, len() with the basic types are not expensive, and it can vary based on the container implementation, but that’s not really the point.

The reason you should use “if x” is the same reason you should use “if x not in y” rather than “if not x in y”. It better expresses the semantics of your operation with the side effect that it may be faster.

Oh yeah, totally agree that it's idiomatic and (in my opinion) cleaner.
Thanks!

Good point. However setting

  def __bool__(self): return self.nonEmpty
would mess up certain methods e.g. .index for nested Arrays as __eq__ is computed elementwise and bool(Array(False, False)) would evaluate to True.

Maybe a warning would be appropriate? (as is the case with ndarrays)

> bool(Array(False, False)) would evaluate to True

Isn't that consistent with the built-in `list`, though, because `bool([False, False])` is True?

My explanation was pretty poor, let me rephrase

For example, when calling

  Array((x, y), (z, w)).index((z, w))
the following piece of code is executed

  bool(Array((x, y)).__eq__((z, w)))
  = bool(Array(False, False))
 
If __bool__ returned whether the Array is nonempty, bool(Array(False, False)) would evaluate to True and the method would wrongly return 0.

You're right that it would be more clear if __bool__ would behave similarly, but since Array computes operations element-wise, it isn't possible.

I think the complaint is that you are using `bool` as a `all()` call on your Arrays.

If you used `all()` in your implementation instead, you could be compatible with the idiomatic use of `bool(my_list)` and the _very_ common `if my_list:` structure could be used with Arrays too (like most people probably would expect from a "better list type")

Regardless, Pandas struggles with the same problem, so you are at least in good company :)