Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #64012

Re: Chanelling Guido - dict subclasses

From Peter Otten <__peter__@web.de>
Subject Re: Chanelling Guido - dict subclasses
Date 2014-01-15 19:35 +0100
Organization None
References <52d5e408$0$29970$c3e8da3$5496439d@news.astraweb.com> <mailman.5494.1389775244.18130.python-list@python.org> <05ff1332-1776-4ac0-88b4-84f8fd323ce3@googlegroups.com>
Newsgroups comp.lang.python
Message-ID <mailman.5540.1389810978.18130.python-list@python.org> (permalink)

Show all headers | View raw


John Ladasky wrote:

> On Wednesday, January 15, 2014 12:40:33 AM UTC-8, Peter Otten wrote:
>> Personally I feel dirty whenever I write Python code that defeats duck-
>> typing -- so I would not /recommend/ any isinstance() check.
> 
> While I am inclined to agree, I have yet to see a solution to the problem
> of flattening nested lists/tuples which avoids isinstance().  If anyone
> has written one, I would like to see it, and consider its merits.

Well, you should always be able to find some property that discriminates 
what you want to treat as sequences from what you want to treat as atoms.

(flatten() Adapted from a nine-year-old post by Nick Craig-Wood
<https://mail.python.org/pipermail/python-list/2004-December/288112.html>)

>>> def flatten(items, check):
...     if check(items):
...         for item in items:
...             yield from flatten(item, check)
...     else:
...         yield items
... 
>>> items = [1, 2, (3, 4), [5, [6, (7,)]]]
>>> print(list(flatten(items, check=lambda o: hasattr(o, "sort"))))
[1, 2, (3, 4), 5, 6, (7,)]
>>> print(list(flatten(items, check=lambda o: hasattr(o, "count"))))
[1, 2, 3, 4, 5, 6, 7]

The approach can of course break

>>> items = ["foo", 1, 2, (3, 4), [5, [6, (7,)]]]
>>> print(list(flatten(items, check=lambda o: hasattr(o, "count"))))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in flatten
  File "<stdin>", line 4, in flatten
  File "<stdin>", line 4, in flatten
  File "<stdin>", line 4, in flatten
  File "<stdin>", line 4, in flatten
  File "<stdin>", line 4, in flatten
  File "<stdin>", line 4, in flatten
  File "<stdin>", line 2, in flatten
RuntimeError: maximum recursion depth exceeded

and I'm the first to admit that the fix below looks really odd:

>>> print(list(flatten(items, check=lambda o: hasattr(o, "count") and not 
hasattr(o, "split"))))
['foo', 1, 2, 3, 4, 5, 6, 7]

In fact all of the following examples look more natural...

>>> print(list(flatten(items, check=lambda o: isinstance(o, list))))
['foo', 1, 2, (3, 4), 5, 6, (7,)]
>>> print(list(flatten(items, check=lambda o: isinstance(o, (list, 
tuple)))))
['foo', 1, 2, 3, 4, 5, 6, 7]
>>> print(list(flatten(items, check=lambda o: isinstance(o, (list, tuple)) 
or (isinstance(o, str) and len(o) > 1))))
['f', 'o', 'o', 1, 2, 3, 4, 5, 6, 7]

... than the duck-typed variants because it doesn't matter for the problem 
of flattening whether an object can be sorted or not. But in a real-world 
application the "atoms" are more likely to have something in common that is 
required for the problem at hand, and the check for it with 

def check(obj):
    return not (obj is an atom) # pseudo-code

may look more plausible.

Back to comp.lang.python | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

Chanelling Guido - dict subclasses Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-01-15 01:27 +0000
  Re: Chanelling Guido - dict subclasses Ned Batchelder <ned@nedbatchelder.com> - 2014-01-14 21:04 -0500
  Re: Chanelling Guido - dict subclasses Terry Reedy <tjreedy@udel.edu> - 2014-01-14 22:48 -0500
  Re: Chanelling Guido - dict subclasses F <f@hop2it.be> - 2014-01-15 07:00 +0000
  Re: Chanelling Guido - dict subclasses Peter Otten <__peter__@web.de> - 2014-01-15 09:40 +0100
    Re: Chanelling Guido - dict subclasses John Ladasky <john_ladasky@sbcglobal.net> - 2014-01-15 08:51 -0800
      Re: Chanelling Guido - dict subclasses Peter Otten <__peter__@web.de> - 2014-01-15 19:35 +0100
      Re: Chanelling Guido - dict subclasses Devin Jeanpierre <jeanpierreda@gmail.com> - 2014-01-15 22:30 -0800
  Re: Chanelling Guido - dict subclasses Mark Lawrence <breamoreboy@yahoo.co.uk> - 2014-01-15 09:10 +0000
  Re: Chanelling Guido - dict subclasses Tim Chase <python.list@tim.thechases.com> - 2014-01-15 05:03 -0600
  Re: Chanelling Guido - dict subclasses Daniel da Silva <var.mail.daniel@gmail.com> - 2014-01-15 19:50 -0500
    Re: Chanelling Guido - dict subclasses Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2014-01-16 17:17 +1300

csiph-web