A shortcut for the first line is:

```
sage: x = polygen(QQ)
```

Then it's a matter of taste which is more elegant: your code, or

```
sage: p = x^6 - 3*x^4 + 5*x^2 - 9
sage: assert not any(p.list()[1::2])
sage: p.parent(p.list()[::2])
x^3 - 3*x^2 + 5*x - 9
```

This code is shorter, but yours iterates instead of constructing a list.

Sadly, `p[1::2]`

and `p[::2]`

don't give the expected result,
the final `:2`

is silently ignored. The code for that is in the
`__getitem__`

method of the class `Polynomial_rational_flint`

,
which is the class of `p`

. Inspecting this method:

```
sage: from sage.rings.polynomial.polynomial_rational_flint import Polynomial_rational_flint
sage: Polynomial_rational_flint.__getitem__??
```

gives

```
def __getitem__(self, n):
"""
Returns coefficient of the monomial of degree `n` if `n` is an integer,
returns the monomials of self of degree in slice `n` if `n` is a slice.
INPUT:
- ``n`` - Degree of the monomial whose coefficient is to be returned
or a slice.
EXAMPLES::
sage: R.<t> = QQ[]
sage: f = 1 + t + t^2/2 + t^3/3 + t^4/4
sage: f[-1], f[0], f[3], f[5] # indirect doctest
(0, 1, 1/3, 0)
sage: f[1:3] # indirect doctest
1/2*t^2 + t
"""
cdef Rational z = PY_NEW(Rational)
cdef Polynomial_rational_flint res = self._new()
cdef bint do_sig = _do_sig(self.__poly)
if isinstance(n, slice):
start, stop, step = n.indices(self.degree() + 1)
if do_sig: sig_on()
fmpq_poly_get_slice(res.__poly, self.__poly, start, stop)
if do_sig: sig_off()
return res
else:
if 0 <= n and n < fmpq_poly_length(self.__poly):
fmpq_poly_get_coeff_mpq(z.value, self.__poly, n)
return z
```

in which we see that in the case where `n`

is an instance of the type `slice`

,
it is split into `start, stop, step`

, and then `step`

is silently dropped
when calling `fmpq_poly_get_slice(res.__poly, self.__poly, start, stop)`

.

Fixing this is not immediate since the flint function `fmpq_poly_get_slice`

only takes start and stop arguments, not a step, see
flint source code.
Maybe this could be a feature request for Flint, and then we could make
the `__get_item__`

method above work!

In the meantime, I wonder if a warning, or a "not implemented" error
should be raised when calling `__get_item__`

with a step other than 1,
since the result is likely to be wrong with respect to the user's expectation.

Going beyond this exploration of your simple example:
of course if you wanted to deal with very general polynomials,
including sparse polynomials or multivariate polynomials,
you would need to deal differently with different
flavours of polynomials, since they have different implementations.

Note that in the symbolic ring you can use

`substitute_expression`

, for example after`sage: x = var('x')`

and`sage: f = x^2 + 1`

then`f.subs_expr(x^2 == x)`

gives`x+1`

. Not sure going to the symbolic ring and back could be called elegant, though.