Coding technique: distinguish using type or abc?
Rob Gaddi
rgaddi at highlandtechnology.invalid
Wed Jan 8 17:33:17 EST 2020
On 1/8/20 1:40 PM, DL Neil wrote:
> Do you prefer to use isinstance() with type() or to refer to collections.abc?
>
>
> This team producing bases statistical analyses for (lesser capable) user-coders
> to utilise with their own experimental 'control code'; faces situations where a
> list-parameter is often only one element long. As is so often the way, amongst
> the 'clients' there are a couple of strong-minded (am not allowed to call them
> "awkward", or otherwise!) user-coder-analysts, who demand that entry of a
> single-element not require them to surround it with "unnecessary"
> square-brackets. Despite complaining, we realise that this is actually quite a
> good practice, and likely save us (as well as 'them') from interface mistakes.
>
> Such single elements appear in both string and numeric formats, but for
> simplicity (here) let's ignore numerics...
>
> The problem rearing its ugly head, is when the string single-element becomes
> input to a for-loop. If we loop around a list, then each element is handled
> individually (as desired). Whereas if the element is a string, then each
> character is treated as if it were a list-element (not)!
>
>
> In Code Review, I noticed that two 'solutions' have been coded.
>
> 1 using type()s to distinguish:
>
> def format_as_list( parameter:Union[ str, list ] )->list:
> if isinstance( parameter, str ):
> parameter_list = [ parameter ]
> elif isinstance( parameter, list ):
> parameter_list = parameter
> else:
> raise NotImplementedError
> return parameter_list
>
> 2 using abstract base classes from PSL.collections to distinguish:
>
> import collections.abc as abc
> def is_list_not_string( parameter:Union[ str, list ] ) -> bool:
> return isinstance( parameter, abc.MutableSequence )
>
> def format_as_list( parameter:str )->list:
> if is_list_not_string( parameter ):
> return parameter
> else:
> return [ parameter, ]
>
> (ignoring implicit assumption/error!)
> NB I've simplified the code and attempted to harmonise the varNMs between snippets.
>
> With our preference for EAFP, I went looking for a way to utilise an exception
> by way of distinguishing between the input-types - but couldn't see how, without
> major artifice (false/purposeless construct which would confuse the next reader
> of the code). That said, I'm wondering if using (or appearing to use) tuples and
> *args might solve the problem - but will have to dig back through the code-base...
>
>
> Meantime, faced with such a challenge, would you recommend utilising one of
> these ideas over the other, or perhaps some other solution?
>
> Are there perhaps circumstances where you would use one solution, and others the
> other?
>
I try to avoid making assumptions, so I wind up with a lot of
if isinstance(parameter, str):
plist = [parameter]
else:
try:
plist = list(parameter)
except TypeError:
plist = [parameter]
Any iterable gets listified unless it's a string, which gets treated the same
way a non-iterable does. EAFP.
More information about the Python-list
mailing list