Re: Try: rather than if :

2015-12-15 Thread jmp

On 12/14/2015 11:38 PM, Vincent Davis wrote:

In the code below try is used to check if handle has the attribute name. It
seems an if statement could be used. Is there reason one way would be
better than another?

def write_header(self):
 handle = self.handle
 try:
 handle.write("# Report_file: %s\n" % handle.name)
 except AttributeError:
 pass
 handle.write("\n")

The specific use case I noticed this was
https://github.com/biopython/biopython/blob/master/Bio/AlignIO/EmbossIO.py#L38

Vincent Davis



Nothing wrong with the try block. However other forms may be 
shorter/more readable.
Since there is 2 attribute lookups in the try block, (write and name) 
it's not clear which one you want to catch (except for the line 
following the except clause but it could not be the case).


Here are 2 alternative forms

1/ handle.write(handle.name if hasattr(handle, 'name') else '')
2/ handle.write(getattr(handle, 'name', ''))

Here's the best solution imo:
3/ assume handle has always a name attribute and don't write code 
handling attribute existence. Instead handle the attribute values:


class Handle:
  def __init__(self):
self.name= None # and the problem is gone

if handle.name : handle.write(handle.name)


By the way, in the use case you've linked, it is written
'handle = self.handle'
at every beginning of each method. Don't follow that rule.


Jm


--
https://mail.python.org/mailman/listinfo/python-list


Re: Try: rather than if :

2015-12-14 Thread Chris Angelico
On Tue, Dec 15, 2015 at 10:48 AM, Vincent Davis
 wrote:
> try:
> write = handel.write
> except AttributeError:
> raise

Just "write = handel.write" :)

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Try: rather than if :

2015-12-14 Thread Vincent Davis
On Mon, Dec 14, 2015 at 4:14 PM, Cameron Simpson  wrote:

> First, notice that the code inside the try/except _only_ fetches the
> attribute.  Your version calls the "write" attribute, and also accesses
> handle.name. Either of those might also emit AttributeError, and should
> probably not be silently caught.
>

​I think the intent of the original code was to check if handle had the
attribute "name", I don't think the attribute "write" was the issue.

So then possibly this based on your suggestion:
try:
write = handel.write
except AttributeError:
raise
try:
name = handel.name
write("# Report_file: %s\n" % name)
except AttributeError:
pass
write("\n")


Vincent Davis
720-301-3003
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Try: rather than if :

2015-12-14 Thread Ian Kelly
On Mon, Dec 14, 2015 at 4:48 PM, Vincent Davis  wrote:
> On Mon, Dec 14, 2015 at 4:14 PM, Cameron Simpson  wrote:
>
>> First, notice that the code inside the try/except _only_ fetches the
>> attribute.  Your version calls the "write" attribute, and also accesses
>> handle.name. Either of those might also emit AttributeError, and should
>> probably not be silently caught.
>>
>
> I think the intent of the original code was to check if handle had the
> attribute "name", I don't think the attribute "write" was the issue.
>
> So then possibly this based on your suggestion:
> try:
> write = handel.write
> except AttributeError:
> raise

Except that catching an exception just to immediately re-raise it is
silly. This would be better:

try:
name = handle.name
except AttributeError:
pass
else:
handle.write("# Report_file: %s\n" % name)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Try: rather than if :

2015-12-14 Thread Vincent Davis
On Mon, Dec 14, 2015 at 4:53 PM, Ian Kelly  wrote:

>
> Except that catching an exception just to immediately re-raise it is
> silly. This would be better:
>
> try:
> name = handle.name
> except AttributeError:
> pass
> else:
> handle.write("# Report_file: %s\n" % name)


​Ya that would be silly.

Thanks​ everyone for the education.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Try: rather than if :

2015-12-14 Thread Cameron Simpson

On 15Dec2015 17:11, Cameron Simpson  wrote:

On 14Dec2015 16:48, Vincent Davis  wrote:

[...]

​I think the intent of the original code was to check if handle had the
attribute "name", I don't think the attribute "write" was the issue.

[...]
Secondly, for your use case "print the name if it has one" I _would_ use 
hasattr:


if hasattr(handle, name):
  write("# Report_file: %s\n" % name)


On reflection, there's also this:

 name = getattr(handle, 'name', repr(handle))
 write("# Report_file: %s\n" % name)

i.e. _always_ identfy the handle, even if it has no nice name.

Cheers,
Cameron Simpson 
--
https://mail.python.org/mailman/listinfo/python-list


Re: Try: rather than if :

2015-12-14 Thread Cameron Simpson

On 14Dec2015 16:48, Vincent Davis  wrote:

On Mon, Dec 14, 2015 at 4:14 PM, Cameron Simpson  wrote:


First, notice that the code inside the try/except _only_ fetches the
attribute.  Your version calls the "write" attribute, and also accesses
handle.name. Either of those might also emit AttributeError, and should
probably not be silently caught.



​I think the intent of the original code was to check if handle had the
attribute "name", I don't think the attribute "write" was the issue.


I have to say that this was not at all evident to me. I think that also argues 
for putting the smallest possible bit of code inside the try/except.



So then possibly this based on your suggestion:
try:
   write = handel.write
except AttributeError:
   raise


Someone has already suggested dropping the try/except altogether for this.


try:
   name = handel.name
   write("# Report_file: %s\n" % name)
except AttributeError:
   pass


Again, I would minimise the stuff in the try/except, so:

 try:
   name = handle.name
 except AttributeError:
   pass
 else:
   write("# Report_file: %s\n" % name)

But in this case, in my code, I do two things:

Firstly, things needing names always get one:

 class Foo:
   def __init__(self, blah, name=None):
 if name is None:
   name = "Foo-%s" % (id(self),)
 self.name = name

Secondly, for your use case "print the name if it has one" I _would_ use 
hasattr:


 if hasattr(handle, name):
   write("# Report_file: %s\n" % name)

The logic feels far clearer to my eye.

Cheers,
Cameron Simpson 
--
https://mail.python.org/mailman/listinfo/python-list


Try: rather than if :

2015-12-14 Thread Vincent Davis
In the code below try is used to check if handle has the attribute name. It
seems an if statement could be used. Is there reason one way would be
better than another?

def write_header(self):
handle = self.handle
try:
handle.write("# Report_file: %s\n" % handle.name)
except AttributeError:
pass
handle.write("\n")

The specific use case I noticed this was
https://github.com/biopython/biopython/blob/master/Bio/AlignIO/EmbossIO.py#L38

Vincent Davis
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Try: rather than if :

2015-12-14 Thread Ian Kelly
On Mon, Dec 14, 2015 at 3:38 PM, Vincent Davis  wrote:
> In the code below try is used to check if handle has the attribute name. It
> seems an if statement could be used. Is there reason one way would be
> better than another?

http://www.oranlooney.com/lbyl-vs-eafp/
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Try: rather than if :

2015-12-14 Thread Cameron Simpson

On 14Dec2015 15:38, Vincent Davis  wrote:

In the code below try is used to check if handle has the attribute name. It
seems an if statement could be used.


Only by using hasattr(), which IIRC does a try/except internally.


Is there reason one way would be
better than another?


try/except is more directly, but hasattr() is shorter. However, consider this: 
I would write your example:



   try:
   handle.write("# Report_file: %s\n" % handle.name)
   except AttributeError:
   pass
   handle.write("\n")


as:

 try:
   write = handle.write
 except AttributeError:
   pass# or complain
 else:
   write("# Report_file: %s\n" % handle.name)
   write("\n")

Two things:

First, notice that the code inside the try/except _only_ fetches the attribute.  
Your version calls the "write" attribute, and also accesses handle.name. Either 
of those might also emit AttributeError, and should probably not be silently 
caught.


Second, notice that as a side effect of the:

 write = handle.write

line we now have the attribute value. If it were an if:

 if hasattr(handle, 'write'):
   write = handle.write
   ... write messages now ...

which is two steps to test and get the attribute. Feels... clunky. Perhaps 
partly because of the scope of a spelling error between the "'write'" string 
and the "handle.write" use below it, but clunky anyway.


Which to use depends on how you weigh readability and directness. But try to 
get decide how mugh of your "if" preference is personal uncomfortableness with 
try/except (for whatever reasons), and then how much those reasons may be 
generally applicable or a personal foible.


But it is your code, your call. What reads better to your eye?

Cheers,
Cameron Simpson 
--
https://mail.python.org/mailman/listinfo/python-list


EAFP and LBYL (was: Try: rather than if :)

2015-12-14 Thread Ben Finney
Vincent Davis  writes:

> In the code below try is used to check if handle has the attribute name. It
> seems an if statement could be used. Is there reason one way would be
> better than another?

The Python community refers to the difference by contrasting “look
before you leap” (LBYL) versus “easier to ask forgiveness than
permission” (EAFP), and tends to prefer the latter.



“It is easier to ask forgiveness than permission” is attributed to
computer programming legend Rear Admiral Grace Hopper (she who
documented the first actual computer bug — a large moth in the wires).

Alex Martelli explores when LBYL and EAFP are each appropriate in Python
.

-- 
 \   “The optimist thinks this is the best of all possible worlds. |
  `\   The pessimist fears it is true.” —J. Robert Oppenheimer |
_o__)  |
Ben Finney

-- 
https://mail.python.org/mailman/listinfo/python-list