Mailing List Archive

Syntax not understood
Hello

In this function

def get4(srcpages):
scale = 0.5
srcpages = PageMerge() + srcpages
x_increment, y_increment = (scale * i for i in srcpages.xobj_box[2:])
for i, page in enumerate(srcpages):
page.scale(scale)
page.x = x_increment if i & 1 else 0
page.y = 0 if i & 2 else y_increment
return srcpages.render()

found here

https://www.blog.pythonlibrary.org/2018/06/06/creating-and-manipulating-pdfs-with-pdfrw/

I do not understand this line:

x_increment, y_increment = (scale * i for i in srcpages.xobj_box[2:])

(scale * i for i in srcpages.xobj_box[2:]) is a generator, a single
object, it should not be possible to unpack it into 2 variables.

x, y = 1 generates an error
x, y = (i for i in range(10)) too

but not

x_increment, y_increment = (scale * i for i in srcpages.xobj_box[2:])

why ?
--
https://mail.python.org/mailman/listinfo/python-list
Re: Syntax not understood [ In reply to ]
Le 04/11/2021 à 16:41, Stefan Ram a écrit :
> ast <ast@invalid> writes:
>> (scale * i for i in srcpages.xobj_box[2:]) is a generator, a single
>> object, it should not be possible to unpack it into 2 variables.
>
> But the value of the right-hand side /always/ is a single object!
>
> A syntax of an assignment statement that has been simplified
> by me but is sufficient for this post is:
>
> target list = source expression
>
> . The evaluation of the source expression yields an object.
>
> If the target list is not a single target, that object must
> be an iterable with the same number of items as there are targets
> in the target list, and the items are assigned, from left to
> right, to the corresponding targets.
>
> A generator object /is/ an iterable, and, here, it apparently
> yields exactly two items.
>
>

understood

It is like:

x, y = (i for i in range(2))

thx
--
https://mail.python.org/mailman/listinfo/python-list
Re: Syntax not understood [ In reply to ]
> x_increment, y_increment = (scale * i for i in srcpages.xobj_box[2:])
>
> (scale * i for i in srcpages.xobj_box[2:]) is a generator, a single
> object, it should not be possible to unpack it into 2 variables.

If you know the exact number of values in the generator, you can do
this. Here is an oversimplified example.

l = [0, 1, 2, 3, 4, 5]
a, b = (elem * 10 for elem in l[:4])
print(a, b) # prints 40 50

This is very fragile code and I would recommend against using it.

- DLD
--
https://mail.python.org/mailman/listinfo/python-list
Re: Syntax not understood [ In reply to ]
On 2021-11-04 at 14:36:48 -0400,
David Lowry-Duda <david@lowryduda.com> wrote:

> > x_increment, y_increment = (scale * i for i in srcpages.xobj_box[2:])
> >
> > (scale * i for i in srcpages.xobj_box[2:]) is a generator, a single
> > object, it should not be possible to unpack it into 2 variables.
>
> If you know the exact number of values in the generator, you can do
> this. Here is an oversimplified example.
>
> l = [0, 1, 2, 3, 4, 5]
> a, b = (elem * 10 for elem in l[:4])
> print(a, b) # prints 40 50
>
> This is very fragile code and I would recommend against using it.

How is that any more fragile than any other operation that destructs (or
doesn't) a tuple?

Is the following fragile:

quotient, remainder = divmod(numerator, denominator)

Would you surround it with try/except, or always unpack it defensively?

result = divmod(numerator, denominator)
if len(result) == 2:
quotient, remainder = result
else:
raise SomeException("divmod didn't work")

If I know where a generator (or an iterator, or a tuple, or a list) came
from, and it's documented to contain/yield a known quantity of values,
then why is it fragile to depend on that?

On the other hand, yes, if I build code that depends on a lot of
unstated relationships between values of questionable (or unknown)
origin, then I am definitely asking for trouble.
--
https://mail.python.org/mailman/listinfo/python-list
Re: Syntax not understood [ In reply to ]
On Fri, Nov 5, 2021 at 6:23 AM <2QdxY4RzWzUUiLuE@potatochowder.com> wrote:
>
> On 2021-11-04 at 14:36:48 -0400,
> David Lowry-Duda <david@lowryduda.com> wrote:
>
> > > x_increment, y_increment = (scale * i for i in srcpages.xobj_box[2:])
> > >
> > > (scale * i for i in srcpages.xobj_box[2:]) is a generator, a single
> > > object, it should not be possible to unpack it into 2 variables.
> >
> > If you know the exact number of values in the generator, you can do
> > this. Here is an oversimplified example.
> >
> > l = [0, 1, 2, 3, 4, 5]
> > a, b = (elem * 10 for elem in l[:4])
> > print(a, b) # prints 40 50
> >
> > This is very fragile code and I would recommend against using it.
>
> How is that any more fragile than any other operation that destructs (or
> doesn't) a tuple?
>

The only part that's fragile, in my opinion, is (from the initial
post) that it's using removal syntax to slice off some, which is
fragile against the original input length:

x_increment, y_increment = (scale * i for i in srcpages.xobj_box[2:])

But since it says "box", I would start by assuming that it has four
elements. (They might be x1,y1,x2,y2 or x,y,w,h but it'll almost
always be four.) So it's not TOO fragile, when working with boxes, but
it is a little less clear that thing[2:] will always give exactly two
results.

ChrisA
--
https://mail.python.org/mailman/listinfo/python-list
Re: Syntax not understood [ In reply to ]
On 2021-11-05 at 06:28:34 +1100,
Chris Angelico <rosuav@gmail.com> wrote:

> On Fri, Nov 5, 2021 at 6:23 AM <2QdxY4RzWzUUiLuE@potatochowder.com> wrote:
> >
> > On 2021-11-04 at 14:36:48 -0400,
> > David Lowry-Duda <david@lowryduda.com> wrote:
> >
> > > > x_increment, y_increment = (scale * i for i in srcpages.xobj_box[2:])
> > > >
> > > > (scale * i for i in srcpages.xobj_box[2:]) is a generator, a single
> > > > object, it should not be possible to unpack it into 2 variables.
> > >
> > > If you know the exact number of values in the generator, you can do
> > > this. Here is an oversimplified example.
> > >
> > > l = [0, 1, 2, 3, 4, 5]
> > > a, b = (elem * 10 for elem in l[:4])
> > > print(a, b) # prints 40 50
> > >
> > > This is very fragile code and I would recommend against using it.
> >
> > How is that any more fragile than any other operation that destructs (or
> > doesn't) a tuple?
> >
>
> The only part that's fragile, in my opinion, is (from the initial
> post) that it's using removal syntax to slice off some, which is
> fragile against the original input length:
>
> x_increment, y_increment = (scale * i for i in srcpages.xobj_box[2:])
>
> But since it says "box", I would start by assuming that it has four
> elements. (They might be x1,y1,x2,y2 or x,y,w,h but it'll almost
> always be four.) So it's not TOO fragile, when working with boxes, but
> it is a little less clear that thing[2:] will always give exactly two
> results.

I won't disagree that most boxes are going to be described by four
elements, in which case slicing off the first two *should* leave two
more (presumably x_increment and y_increment).

So if you're saying that all that's missing is a description of
srcpages.xobj_box, then I agree. :-) But such is life on a mailing
list where posters don't always give their questions the context they
deserve.
--
https://mail.python.org/mailman/listinfo/python-list
Re: Syntax not understood [ In reply to ]
On Fri, Nov 5, 2021 at 6:45 AM <2QdxY4RzWzUUiLuE@potatochowder.com> wrote:
> > But since it says "box", I would start by assuming that it has four
> > elements. (They might be x1,y1,x2,y2 or x,y,w,h but it'll almost
> > always be four.) So it's not TOO fragile, when working with boxes, but
> > it is a little less clear that thing[2:] will always give exactly two
> > results.
>
> I won't disagree that most boxes are going to be described by four
> elements, in which case slicing off the first two *should* leave two
> more (presumably x_increment and y_increment).

Exactly. To an experienced Python programmer, it's obvious that that
line of code is scaling the dimensions and assigning them. But if you
aren't comfortable with that, then it isn't so obvious.

Perhaps it'd be better to spell it as [-2:], which will clearly give
two results regardless of the length of the input (unless it's too
short). But that's minor IMO.

> So if you're saying that all that's missing is a description of
> srcpages.xobj_box, then I agree. :-) But such is life on a mailing
> list where posters don't always give their questions the context they
> deserve.

Indeed :)

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