Coding technique: distinguish using type or abc?
Do you prefer to use isinstance() with type() or to refer to
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
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, ]
(ignoring implicit assumption/error!)
NB I've simplified the code and attempted to harmonise the varNMs
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?