Live data from Hacker News

Counting Things in Python: A History

treyhunner.com

11–20 of 61 posts

Re: Counting Things in Python: A History

#11

  $ txr
  This is the TXR Lisp interactive listener of TXR 123.
  Use the :quit command or type Ctrl-D on empty line to exit.
  1> [hash-update [group-by identity
                            '(brown red green yellow yellow
                              brown brown black)]
                  length]
  #H(() (green 1) (red 1) (brown 3) (black 1) (yellow 2))
Form a hash by grouping like items into lists. The identity function is the key in the hash and the basis for equality, so the keys are colors, and the values are lists of colors.

Then update the hash values by filtering through the length function.

Re: Counting Things in Python: A History

#12

The try block method would be considered bad in most languages, and I hope it is considered bad in Python as well. Using exception handling as part of a normal flow of control is bad style, bad taste, and bad for performance. EDIT: I'm glad to see the Python documentation addresses this: https://docs.python.org/2/faq/design.html#how-fast-are-excep...

[deleted]

Re: Counting Things in Python: A History

#13

The try block method would be considered bad in most languages, and I hope it is considered bad in Python as well. Using exception handling as part of a normal flow of control is bad style, bad taste, and bad for performance. EDIT: I'm glad to see the Python documentation addresses this: https://docs.python.org/2/faq/design.html#how-fast-are-excep...

[deleted]

Re: Counting Things in Python: A History

#14

The try block method would be considered bad in most languages, and I hope it is considered bad in Python as well. Using exception handling as part of a normal flow of control is bad style, bad taste, and bad for performance. EDIT: I'm glad to see the Python documentation addresses this: https://docs.python.org/2/faq/design.html#how-fast-are-excep...

It really depends. Usually, you would do something like this in Python:

def whatever(some_string): try: return some_string.split() except AttributeError: return some_other_parsing_stuff(some_string)

Instead of checking the type of some_string, or seeing if it has the method split. Reason is: it's more straight forward, and it instantly tells the reader this function is meant to handle strings, and it will split them. If it gets a not-string for some reason, oh well, it'll still handle it.

You would check for values in a circumstance like this:

def dict_breaker(some_dict): if 'items' in some_dict: return parse_some_items(some_dict['items'])

Re: Counting Things in Python: A History

#15

The try block method would be considered bad in most languages, and I hope it is considered bad in Python as well. Using exception handling as part of a normal flow of control is bad style, bad taste, and bad for performance. EDIT: I'm glad to see the Python documentation addresses this: https://docs.python.org/2/faq/design.html#how-fast-are-excep...

It really depends. Usually, you would do something like this in Python: def whatever(some_string): try: return some_string.split() except AttributeError: return some_other_parsing_stuff(some_string) Instead of checking the type of some_string, or seeing if it has the method split. Reason is: it's more straight forward, and it instantly tells the reader this function is meant to handle strings, and it will split them.…

The latter isn't actually the typical Python style. As the article discusses, Python generally prefers "EAFP"[1] to "LBYL"[2], e.g.

  def dict_breaker(some_dict):
      try:
          return parse_some_items(some_dict['items'])
      except KeyError:
          pass
    
Or even

  def dict_breaker(some_dict):
      try:
          items = some_dict['items']
      except KeyError:
          pass
      else:
          return parse_some_items(items)
These versions may be more efficient (only have to do one hash and interaction with the hashmap, but this probably won't be visible with integers/short strings), and don't suffer from race conditions in concurrent code with the hashmap being modified between the check and the use (yes, this can occur even with GIL).

[1]: https://docs.python.org/2/glossary.html#term-eafp [2]: https://docs.python.org/2/glossary.html#term-lbyl

Re: Counting Things in Python: A History

#16

$ txr This is the TXR Lisp interactive listener of TXR 123. Use the :quit command or type Ctrl-D on empty line to exit. 1> [hash-update [group-by identity '(brown red green yellow yellow brown brown black)] length] #H(() (green 1) (red 1) (brown 3) (black 1) (yellow 2)) Form a hash by grouping like items into lists. The identity function is the key in the hash and the basis for equality, so the keys are colors, and t…

I guess this is off topic, but neat language.

But that algorithm allocates a bunch of intermediate lists and iterates through the hash table when it doesn't need to. Here it is in common lisp:

    (defun count-elements (lst)
      (loop
         with rval = (make-hash-table)
         for val in lst
         do
           (incf (gethash val rval 0))
         finally (return rval)))

Re: Counting Things in Python: A History

#17

The try block method would be considered bad in most languages, and I hope it is considered bad in Python as well. Using exception handling as part of a normal flow of control is bad style, bad taste, and bad for performance. EDIT: I'm glad to see the Python documentation addresses this: https://docs.python.org/2/faq/design.html#how-fast-are-excep...

It's not considered quite that bad. In many languages, using exceptions for non-exceptional flow control is bad style. Python is a bit more ambivalent about this, for instance take a look at the iterator protocol which uses an exception to signal the iterator is done.

https://docs.python.org/2/library/stdtypes.html#iterator-typ...

Re: Counting Things in Python: A History

#18
post #15

Earlier quoted context omitted.

It really depends. Usually, you would do something like this in Python: def whatever(some_string): try: return some_string.split() except AttributeError: return some_other_parsing_stuff(some_string) Instead of checking the type of some_string, or seeing if it has the method split. Reason is: it's more straight forward, and it instantly tells the reader this function is meant to handle strings, and it will split them.…

The latter isn't actually the typical Python style. As the article discusses, Python generally prefers "EAFP"[1] to "LBYL"[2], e.g. def dict_breaker(some_dict): try: return parse_some_items(some_dict['items']) except KeyError: pass Or even def dict_breaker(some_dict): try: items = some_dict['items'] except KeyError: pass else: return parse_some_items(items) These versions may be more efficient (only have to do one ha…

Is there a reason you chose to `pass` instead of the more explicit `return None`? The former seems like it would be less idiomatic since its return value is not explicitly stated.

Re: Counting Things in Python: A History

#19
post #18
post #15

Earlier quoted context omitted.

The latter isn't actually the typical Python style. As the article discusses, Python generally prefers "EAFP"[1] to "LBYL"[2], e.g. def dict_breaker(some_dict): try: return parse_some_items(some_dict['items']) except KeyError: pass Or even def dict_breaker(some_dict): try: items = some_dict['items'] except KeyError: pass else: return parse_some_items(items) These versions may be more efficient (only have to do one ha…

Is there a reason you chose to `pass` instead of the more explicit `return None`? The former seems like it would be less idiomatic since its return value is not explicitly stated.

To emulate the parent exactly e.g. maybe it is just the prefix of the "dict_breaker" function and other things happen later if the key can't be found.

Re: Counting Things in Python: A History

#20
post #7

The try block method would be considered bad in most languages, and I hope it is considered bad in Python as well. Using exception handling as part of a normal flow of control is bad style, bad taste, and bad for performance. EDIT: I'm glad to see the Python documentation addresses this: https://docs.python.org/2/faq/design.html#how-fast-are-excep...

Exceptions in python have historically been very cheap.

That's not true.

There was a paper at the 1997 Python conference on this topic titled "Standard Class Exceptions in Python". A copy is at https://web.archive.org/web/20030610173145/http://barry.wars... . It evaluated the performance of try/except vs. has_key and concluded:

> This indicates that the has_key() idiom is usually the best one to choose, both because it is usually faster than the exception idiom, and because its costs are less variable.

The take-home lesson is that actually raising an exception in Python 1.5 was about 10x more expensive than a function call, but the try/except block when there is no exception was not expensive.

Post reply on HN