1

First of all, I know the difference between if and try and I am perfectly aware that their purposes are completely different -while one makes tests, the other manages errors. However, in this particular case, is it better to use if or try ?

#option1
def getListRank(self):
    for point in self.soup.findAll('td',class_="rank-cell"):
        p = (point.get_text().replace('\t','').replace('\n','')
                             .replace('\r','').replace(',',''))
        if 'T' in p:
            self.listRk.append(int(p.replace('T',''))
        else:
            self.listRk.append(int(p))
    return self.listRk 

I am very tempted to use the following option2, given the fact that I know that the only reason that could prevent from turning p into an integer is the presence of that 'T'. Therefore, would it be unusual or less efficient to write this :

#option2
def getListRank(self):
    for point in self.soup.findAll('td',class_="rank-cell"):
        p = (point.get_text().replace('\t','').replace('\n','')
                             .replace('\r','').replace(',',''))
        try:
            self.listRk.append(int(p))
        except:
            self.listRk.append(int(p.replace('T',''))                
    return self.listRk

I ask the questions because I read this before so I assume that it is "pythonic". However if there is a piece of explanation/convention I am more than interested.

Thanks in advance

Dirty_Fox
  • 1,611
  • 4
  • 20
  • 24
  • 11
    If using an exception handler, do not use Pokemon-style handling; you do not want to *catch them all*. Catch the specific exception only, here that is `except ValueError:`. – Martijn Pieters Aug 07 '15 at 11:34
  • Related: [Python Forgiveness vs. Permission and Duck Typing](https://programmers.stackexchange.com/a/175663) – Martijn Pieters Aug 07 '15 at 11:35
  • 7
    Why bother at all? If `'T'` is not in `p`, then `p.replace('T','')` is just the same as `p` – tobias_k Aug 07 '15 at 11:35
  • @tobias_k yes of course. It was just to take an example. Probably not the best one though especially when I used so many replace before. Thanks anyway. – Dirty_Fox Aug 07 '15 at 11:47
  • 1) A general rule-of-thumb for situations where `if` or `try:...except` both seem appropriate: if you expect a substantial proportion of your cases to raise the exception then using `if` will be faster. 2) As others have said, don't use naked `except` clauses (except at the end of a chain of `except` blocks where you want to do something & then re-raise the exception). 3) Although I'm a big fan of avoiding regex when `str.` methods can do the job, I suggest giving serious thought to using a compiled regex to remove those chars rather than a chain of 4 `.replace()` calls. – PM 2Ring Aug 07 '15 at 11:59
  • 1
    Also, make sure to add as little stuff as possible in the `try` block. Thus `try: p = int(p); except ValueError: p = int(p.replace('T',''); self.listRk.append(p)` would be much better. – Markus Meskanen Aug 07 '15 at 12:10

2 Answers2

2

Don't use either. Remove T along with the other characters, as @tobias_k suggested; then you know that int(p) will succeed. You can do this more easily using re.sub as well, simplifying this enough to use a list comprehension instead of a for loop.

import re

to_replace = re.compile(r'\t|\n|\r|T|,')
def getListRank(self):
    points = self.soup.findAll('td', class_="rank-cell")

    self.listRk = [int(re.sub(to_replace, "", p.get_text())) for p in points]
    return self.listRk

You can also use str.translate to remove your set of characters.

self.listRk = [int(p.get_text().translate(None, "\r\n\tT,")) for p in points]
chepner
  • 497,756
  • 71
  • 530
  • 681
  • May I humbly suggest compiling that regex? :) – PM 2Ring Aug 07 '15 at 12:01
  • I'm not positive, but I think it gets compiled and cached after the first call to `re.sub`. It wouldn't hurt, though. I'm partial to using `str.translate` instead, though. – chepner Aug 07 '15 at 12:03
  • Ah. The [re docs](https://docs.python.org/2/library/re.html#module-contents) _do_ say "Most non-trivial applications always use the compiled form" but I never interpreted that to mean that the non-trivial `re` methods automatically compile non-compiled regexes for you. Interesting... In principle, I like `str.translate` too, since translate tables can do their stuff without branching, and I'd commonly use that approach in C, but in Python I keep forgetting it exists. :) – PM 2Ring Aug 07 '15 at 12:23
  • I forgot about it, too, which is why I used `re.sub` first :) – chepner Aug 07 '15 at 13:01
  • Thanks for translate ! This will help me a lot ! – Dirty_Fox Aug 07 '15 at 13:10
0

At least in CPython's interpreter, exceptions really don't cost much more, and are sometimes cheaper, particularly if the test would require more Python level code, while the exception would be raised implicitly by a C layer function.

The reason to choose if checks over exceptions is usually a matter of style; save exceptions for actual exceptional cases, not as a generic control flow mechanism. That said, Python is all about EAFP, so it tends to use exceptions for less exceptional purposes.

Just please, for the love of god, don't use bare except blocks. Catch the exception you expect, and no more, because otherwise you'll catch stuff that should never have been caught, e.g. if you typo append as apend, the AttributeError will be caught.

Of course, in your particular case, you could just skip the test completely.

self.listRk.append(int(p.replace('T',''))

works whether or not a T is in your string after all. Checking for it is pointless, just get rid of it if it's there and convert to int.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • 1
    [European Association of Fish Pathologists](http://eafp.org)? That definitely sounds like a Pythons sketch... ;) [Easier to Ask for Forgiveness than Permission](http://stackoverflow.com/questions/404795/lbyl-vs-eafp-in-java). – AMR Aug 07 '15 at 12:12
  • 1
    The link for EAFP does redirect to Python's syntax Wikipedia article. I suppose I should provide [the direct link](https://en.wikipedia.org/wiki/Python_syntax_and_semantics#Exceptions) in case those damn fish pathologists steal the redirect. :-) – ShadowRanger Aug 07 '15 at 17:53