Christopher Barker writes:

 > But though Python blurs the lines between various callables and
 > functions, there is a general "sense" of how they are used. And for
 > the most part, zip is not used like a class. WE "use" classes,
 > usually, by creating instances, and then calling various methods on
 > them, etc.

I think this is a distinction without a difference at the margin.  In
the end, all callables return objects, aka instances.  The class
*statement* is special, of course (although to me it's remarkable how
little is special about it).  But then consider factory functions.
>From the outside, what's special about them is that conventionally
they always return objects from a specific class, and that's why they
get a special name.  These distinctions are very useful to humans
thinking about a program (well, they are to me!), but they're fuzzy.

So of course zip can be said to be used like a class.  Its instances
are constructed by calling it, the most common (only in practice?) 
method call is .__iter__, it's invariably called implicitly in a for
statement, and usually the instance is ephemeral (ie, discarded when
the for statement is exited).  But it needn't be.  Like any iterator,
if it's not exhausted in one iteration context, you can continue it
later.  Or explicitly call next on it.

 > a zip instance on the other hand, returns an iterable, that does not
 > provide any other methods or uses.

A zip instance *is* an iterator (though that's not in its name), and
it has quite a few methods ;-) as you can check with dir().  In
particular it has __next__.

 > So while yes, alternate constructors are a common pattern, I don't
 > think they are a common pattern for classes like zip.

That's a matter of programming style, I think.  There's no real
difference between

    zip(a, b, length='checksame')

and 

    zip.checksame(a, b)

They just initialize an internal attribute differently, which may as
well be an Enum or even a few named class constants.

I think (after the initial shock ;-) I like the latter *better*,
because the semantics of checksame and longest are significantly (to
me, anyway) different.  checksame is a constraint on correct behavior,
and explicitly elicits an Exception on invalid input.  longest is a
variant specification of behavior on a certain class of valid input.
I'm happier with those being different *functions* rather than values
of an argument.  YMMV, of course.

There's another possibility, as well:

    zip(a,b).checksame()

but this is bad style IMO (it would have to return self or you
couldn't "for pair in zip(a,b).checksame()", and I don't like methods
that both mutate an object and return self, though some folks do).
_______________________________________________
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/RGVBHDRXZOQO2KJOLSO2TSQCEKUEQLKX/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to