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

Reply via email to