On Sun, Sep 29, 2019 at 09:05:19AM -0700, Christopher Barker wrote:

> And after this code is run, now what? you don't know anything about HOW you
> can subscript that object -- can you use an index, can you use a key, can
> you do something really wierd and arbitrary:

That applies to many interface checks. Both the built-in callable() and 
the Callable ABC don't tell you what arguments the object accepts, or 
what it does; the Sequence ABC check doesn't tell you what valid indexes 
are accepted. People may assume that valid indexes go from 0 through 
len-1 but we can make sequences that work with 1-based sequences, or 
like Fortran, with any bounds at all.

Including virtual "sequences" that accept indexes from -infinity to 
infinity, with no length.

"Consenting adults" applies. The ABC checks only test for the presence 
of an interface, they don't necessarily make guarantees about what the 
interface will do.


 
> So if you think you *may* have a "callable_with_an_integer" -- the thing to
> do is:
> 
> try:
>     result = squares[5]
> except TypeError:
>     print("Opps, couldn't do that")

I know that's meant in good faith, but please be careful of telling me 
what I should do on the basis of a wild guess of what my needs are. I've 
been programming in Python since 1.5 was the latest and greatest, and I 
think I'm capable of judging when I want to use a try...except EAFP 
check rather than a LBYL check for an interface.

And even if I personally am not, this is not about *me*. The community 
as a whole is, which is why Python supports ABCs and isinstance. If you 
want to argue against that, that ship has not only sailed but it's 
already docked at the destination and the passengers disembarked :-)


> Now that I think about it a bit more, that example *could* make sense, but
> only if what you are trying to do is make an indexable lazy-evaluated
> infinite sequence of all the squares -- 

Well spotted :-)


> in which case, you'd want to put a bit more in there.

I'm listening.


> And now that I think about it, there doesn't appear to
> be an ABC for something that can be indexed and iterated, but does not have
> a length.

Exactly!

Don't forget that you don't need __iter__ or length to be iterable:

    py> class Example:
    ...     def __getitem__(self, idx):
    ...             if idx in range(0, 4): return "spam"*idx
    ...             raise IndexError
    ...
    py> list(Example())
    ['', 'spam', 'spamspam', 'spamspamspam']



> However, we need to think more about what ABCs are *for* anyway -- given
> Python's "magic method" system and Duck Typing, you can essentially create
> types that have any arbitrary combination of functionality -- do we need an
> ABC for every one? Obviously not.

I don't think it is so obvious.

Clearly we can't have an ABC for every imaginable combination of magic 
methods. There would be hundreds. What would we name them?

We should (and do!) have ABCs for the most common combinations, like 
Sequence, MutableMapping, Container etc.

And we should (so I am arguing) have ABCs for the underlying building 
blocks, the individual magic methods themselves. Developers can then 
combine those building blocks to make their own application-specific 
combinations.

But without those composable building blocks, we're reduced to testing 
for dunders by hand, which is problematic because:


- people get it wrong, using ``hasattr(instance, dunder)``

- ``getattr(type(instance), dunder, None) is not None`` is 
  apparently still wrong, since that's not what collections.abc 
  does, and presumably it has a good reason for not doing so.

- being part of the implementation, rather than public interface,
  in principle dunders may change in the future.


Obvious well-known dunders like __len__ will probably never go away. But 
the obvious and well-known dunder __cmp__ went away, and maybe one day 
the Sized protocol will change too. If you want to future-proof your 
code, you should test for the Sized interface rather than directly 
testing for the __len__ magic method.


-- 
Steven
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/F2RTHGB4MPECCUKFVOBRLYD5P3T2AJ3F/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to