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.
--
https://mail.python.org/mailman/listinfo/python-list