A variant of the problem is the "occurs check", used in theorem proving:
Removing the occurs check reduces the cost of unifying two terms (t1, t2)
from *O(size(t1) + size(t2))* to *O(min(size(t1), size(t2)))*, which is why
Prolog implementations don't do the occurs check by default (but provide
unify_with_occurs_check and acyclic_term predicates for when the check is
One use for cyclic terms is in representing grammars. Of course, the loops
can be avoided by changing the representation from a graph to a BNF-style
set of clauses - that is, by naming the nodes.
Detecting cycles will involve a lot of bikeshedding. (Sorry, couldn't
Indeed. That really brought a smile to my face. Thank you.
As I recall, bikeshedding is endless discussion (cycles again) of the
COLOUR to paint the bikeshed. And in mathematics there's the topic of
By the way, according to wikipedia, the convention of using colors
originates from the coloring of the countries of a map, as in the famous
Once again, thank you for your careful attention and sense of humour.
Yep, thanks for the explanation!
After some more research into this it appears this exact situation is
accounted for within the `SQLAlchemy` library (reference:
https://github.com/sqlalchemy/sqlalchemy/issues/5810)! Additionally, due
to the complications brought up in this thread it seems like it's probably
best to leave `__eq__` as the default implementation.
Thanks for expanding my knowledge and Happy New Year! 🎊
On Thu, Dec 31, 2020 at 4:40 PM Rob Cliffe <rob.cliffe(a)btinternet.com>
> > You bring up a good point regarding how to determine iterable equality.
> For example, with your last example, I had no idea that the same iterable
> behavior could produce radically different results between cyclers. To be
> quite honest, I don't really understand what causing this quirky behavior.
> Assuming that you refer to Steven D'Aprano's example:
> I didn't understand it either until I played with it a bit. If I
> remember correctly it started something like this:
> it = iter([1,2,3])
> a = cycle(it)
> b = cycle(it)
> Now cycle() reads elements from the iterator until it is exhausted,
> meanwhile storing them. Then it cycles through the stored copies. The
> problem is that a and b point to the *same* iterator and interfere with
> one another. So:
> next(a) # gets 1 from 'it', stores 1, and returns 1
> next(b) # gets 2 from 'it', stores 2, and returns 2
> next(a) # gets 3 from 'it', stores 3, and returns 3
> Now the iterator is exhausted. So subsequent calls of next(a) will
> cycle through a's stored elements, viz. 1 and 3. Subsequent calls of
> next (b) will repeat b's only stored element, viz 2.
> If instead we wrote:
> a = cycle(iter([1,2,3]))
> b = cycle(iter([1,2,3]))
> then although a and b *don't* refer to the *same iterator*, they *will*
> behave identically.
> It seems to me that this makes trying to define "equality" of cycles
> Happy New Year
> Rob Cliffe
Sorry -- I can't find the thread, but there was a discussion on this list
about whether there should be a built in for clearing the terminal screen.
I'm was on the fence about it -- but one more data point:
One of my beginning Python students just submitted code with this in it:
Function: clear_screen() (Windows/Unix)
Process: Clear Screen
if (opSys == 'Windows'):
Which makes me think -- yes, it would be nice to have that available in the
standard lib somewhere.
Christopher Barker, PhD
Python Language Consulting
- Scientific Software Development
- Desktop GUI and Web Development
- wxPython, numpy, scipy, Cython
I am trying to release comfortable dataclass unpacking using `**` operator. Now I have 5 different ways to do it.
But not a single good one. Confused by the implementation of the unpacking operator.
So when I try to unpack any custom class, I get the error:
`type object argument after ** must be a mapping, not MyClass`
Ok, nothing special. I need to use `collections.abc.Mapping` right?
Now I need to implement: `__getitem__`, `__iter__`, `__len__`. Not a problem.
But additionally I get: `keys`, `items`, `values`.
Hey, I don't need them. I don't need the full mapping functionality. I only need the double asterisk to work.
Right, we have a duck typing!
We throw out `abc.Mapping`. What do we need to implement?
It's `__getitem__` and `keys`. Wtf `keys`?
I am looking at Python Data model: https://docs.python.org/3/reference/datamodel.html
There many operators, and they depend on special double underscore methods.
Hmm, I don't see unpack operators there, it's strange.
But why it's `keys`? Because the historical is `dict`?
I think a dependency on `__iter__` is more preferable and expectable over a userspace named `keys`.
Actually, `items()` is more predictable.
But this is not the end.
The `__getitem__` overload is often used for additional checking.
I think `__iter__` and `keys` should only return a valid keys.
Therefore, we don't need to further check them when unpacking. At the very least, we must control this.
And in the end.
`Mapping` keys can be `Any` type. `Unpack` keys must be `str` type.
Some `Mapping` can be unpackable and some `Unpack` can be mappable.
* Add new `collections.abc.Unpack` abstract layout for `**` unpack.
* Add new special method like:
if issubclass(self, collections.abc.Mapping): # Really overload this method in `Mapping` and `dict`.
keys = self.keys() # or return self.items()?
keys = iter(self)
return ((k, self[k]) for k in keys)
* Update the implementation of the unpack operator to use the `__unpack__` function.
As a result:
* We can make the class unpackable without the advanced `Mapping` functionality.
* We can control the unpacking process separately.
* We throw away userspace named dependencies.
* I think we are making behavior more predictable.
What do you think about it?
As the title suggests, I am requesting an user defined __eq__ method for
the itertools.cycle class. A suggestion for how equivalency might work is
that __eq__ would return True if two cyclers have the same iterable and are
at the same location in their cycle and False in any other condition.
Thank you for considering my suggestion,