text: user292: I'm using pybedtools to process data, and at some point, I loop over a BedTool object and use unpacking to extract coordinates from the Interval:
  for interval in my_bedtool:
      (chrom, start, end, _, _, strand) = interval
  
  Suppose I want to compute the interval length, as follows:
      length = end - start
  
  This results in a TypeError: unsupported operand type(s) for -: 'str' and 'str'.
  It happens that the unpacked end and start variables are strings.
  Converting them to ints is probably suboptimal given that Intervals can be created by providing ints for the coordinates:
  from pybedtool import Interval
  interval = Interval("X", 0, 100, strand="+")
  
  The start and end attributes of an Interval are ints.
  I could do:
      (chrom, start, end, strand) = (
          interval.chrom, interval.start, interval.end, interval.strand)
  
  But I think this looks a bit ugly.
  Is there a better approach?
  
  user292: The reason why unpacking an Interval results in strings instead of ints might be related to how indexing by position works.
  Even without considering the string/int issue, it seems slightly more efficient to access the interval's attributes rather than unpacking them directly:
  In [311]: %timeit [(chrom, start, end, strand) for (chrom, start, end, _, _, strand) in my_bedtool]
  306 ms ± 26.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
  
  In [312]: %timeit [(interval.chrom, interval.start, interval.end, interval.strand) for interval in my_bedtool]
  238 ms ± 24.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
  
  To resolve the ugliness issue, attribute access can be made more compact through the use of operator.attrgetter:
  In [313]: from operator import attrgetter
  
  In [314]: get_interval_attrs = attrgetter("chrom", "start", "stop", "strand")
  
  In [315]: %timeit [get_interval_attrs(interval) for interval in my_bedtool]
  239 ms ± 26.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
  
  
original_text: 292: <p>I'm using <a href="https://daler.github.io/pybedtools" rel="nofollow noreferrer">pybedtools</a> to process data, and at some point, I loop over a <code>BedTool</code> object and use <a href="http://treyhunner.com/2018/03/tuple-unpacking-improves-python-code-readability/" rel="nofollow noreferrer"><em>unpacking</em></a> to extract coordinates from the <code>Interval</code>:</p>
  
  <pre><code>for interval in my_bedtool:
      (chrom, start, end, _, _, strand) = interval
  </code></pre>
  
  <p>Suppose I want to compute the interval length, as follows:</p>
  
  <pre><code>    length = end - start
  </code></pre>
  
  <p>This results in a <code>TypeError: unsupported operand type(s) for -: 'str' and 'str'</code>.</p>
  
  <p>It happens that the unpacked <code>end</code> and <code>start</code> variables are strings.
  Converting them to ints is probably suboptimal given that <code>Interval</code>s can be created by providing ints for the coordinates:</p>
  
  <pre><code>from pybedtool import Interval
  interval = Interval("X", 0, 100, strand="+")
  </code></pre>
  
  <p>The <code>start</code> and <code>end</code> attributes of an <code>Interval</code> are ints.</p>
  
  <p>I could do:</p>
  
  <pre><code>    (chrom, start, end, strand) = (
          interval.chrom, interval.start, interval.end, interval.strand)
  </code></pre>
  
  <p>But I think this looks a bit ugly.</p>
  
  <p>Is there a better approach?</p>
   292: <p>The reason why unpacking an <code>Interval</code> results in strings instead of ints might be related to how <a href="https://daler.github.io/pybedtools/intervals.html#indexing-into-interval-objects" rel="nofollow noreferrer">indexing by position</a> works.</p>
  
  <p>Even without considering the string/int issue, it seems slightly more efficient to access the interval's attributes rather than unpacking them directly:</p>
  
  <pre><code>In [311]: %timeit [(chrom, start, end, strand) for (chrom, start, end, _, _, strand) in my_bedtool]
  306 ms ± 26.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
  
  In [312]: %timeit [(interval.chrom, interval.start, interval.end, interval.strand) for interval in my_bedtool]
  238 ms ± 24.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
  </code></pre>
  
  <p>To resolve the ugliness issue, attribute access can be made more compact through the use of <code>operator.attrgetter</code>:</p>
  
  <pre><code>In [313]: from operator import attrgetter
  
  In [314]: get_interval_attrs = attrgetter("chrom", "start", "stop", "strand")
  
  In [315]: %timeit [get_interval_attrs(interval) for interval in my_bedtool]
  239 ms ± 26.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
  </code></pre>
  