Python 3.0 - is this true?

Discussion in 'Python' started by walterbyrd, Nov 8, 2008.

  1. walterbyrd

    walterbyrd Guest

    I have read that in Python 3.0, the following will raise an exception:

    >>> [2, 1, 'A'].sort()


    Will that raise an exception? And, if so, why are they doing this? How
    is this helpful? Is this new "enhancement" Pythonic?
     
    walterbyrd, Nov 8, 2008
    #1
    1. Advertising

  2. walterbyrd

    Peter Otten Guest

    walterbyrd wrote:

    > I have read that in Python 3.0, the following will raise an exception:
    >
    >>>> [2, 1, 'A'].sort()

    >
    > Will that raise an exception?


    Yes.

    >>> [2, 1, "a"].sort()

    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    TypeError: unorderable types: str() < int()

    > And, if so, why are they doing this? How
    > is this helpful? Is this new "enhancement" Pythonic?


    Is 1 > "A"? Is ord("B") > "A", "11" > 10?
    What happens for sorted([datetime.time(), "now"])?

    As the Zen puts it:

    "In the face of ambiguity, refuse the temptation to guess."

    So yes, I think this is an enhancement, and a pythonic one.

    Peter
     
    Peter Otten, Nov 8, 2008
    #2
    1. Advertising

  3. walterbyrd <> writes:

    > I have read that in Python 3.0, the following will raise an exception:
    >
    >>>> [2, 1, 'A'].sort()

    >
    > Will that raise an exception?


    Yes. In fact, plenty of objects of different types aren't comparable
    anymore.

    > And, if so, why are they doing this?


    How is it helpful to be able to sort things which have no natural order?

    > How is this helpful?


    It goes well with duck typing. It lets you know when you things happen
    that you don't mean to happen.

    > Is this new "enhancement" Pythonic?


    By definition!

    --
    Arnaud
     
    Arnaud Delobelle, Nov 8, 2008
    #3
  4. On Sat, 08 Nov 2008 19:02:28 +0000, Arnaud Delobelle wrote:

    >> And, if so, why are they doing this?

    >
    > How is it helpful to be able to sort things which have no natural order?


    Assuming you need to sort arbitrary types, then you have to choose an
    order, even if it is arbitrary, so long as it's consistent.

    I agree that Python shouldn't try to guess how to order incomparable
    types, nor how to order unorderable types, but I'm pretty sure that by
    using the key argument to sort you can specify your own ordering. I don't
    have Python 3 installed here, but some variation on this will probably
    work:

    >>> alist = [2+3j, -4+5j, 8+2j, 1-7j, 6]
    >>> sorted(alist, key=str)

    [(-4+5j), (1-7j), (2+3j), (8+2j), 6]



    Define your own ordering if you need to sort incomparable types.



    --
    Steven
     
    Steven D'Aprano, Nov 9, 2008
    #4
  5. walterbyrd

    walterbyrd Guest

    On Nov 8, 7:44 pm, Steven D'Aprano <st...@REMOVE-THIS-
    cybersource.com.au> wrote:

    > Define your own ordering if you need to sort incomparable types.


    If you starting new, I suppose you can always work around this new
    enhancement. But, couldn't this cause a lot of backward compatibility
    issues?

    Also, I thought that part of the python philosophy was to allow any
    sort of object in a list, and to allow the same methods to work with
    whatever was in list.
     
    walterbyrd, Nov 9, 2008
    #5
  6. walterbyrd

    walterbyrd Guest

    On Nov 8, 12:02 pm, Arnaud Delobelle <> wrote:

    > It goes well with duck typing.  It lets you know when you things happen
    > that you don't mean to happen.


    But doesn't that also make the language less flexible?

    For example, if I used C, I would never have to worry about assigning
    a float to an integer variable. The language will not allow it. I
    thought that python's flexibility, in regard to that sort of thing,
    was supposed to be one of python's great strengths.

    Would it be better if python lists only accepted one type of data?
    Wouldn't that even go further to let you know when things happen, that
    you don't mean to happen?
     
    walterbyrd, Nov 9, 2008
    #6
  7. walterbyrd

    Terry Reedy Guest

    Steven D'Aprano wrote:
    > On Sat, 08 Nov 2008 19:02:28 +0000, Arnaud Delobelle wrote:
    >
    >>> And, if so, why are they doing this?

    >> How is it helpful to be able to sort things which have no natural order?

    >
    > Assuming you need to sort arbitrary types, then you have to choose an
    > order, even if it is arbitrary, so long as it's consistent.
    >
    > I agree that Python shouldn't try to guess how to order incomparable
    > types, nor how to order unorderable types, but I'm pretty sure that by
    > using the key argument to sort you can specify your own ordering. I don't
    > have Python 3 installed here, but some variation on this will probably
    > work:
    >
    >>>> alist = [2+3j, -4+5j, 8+2j, 1-7j, 6]
    >>>> sorted(alist, key=str)

    > [(-4+5j), (1-7j), (2+3j), (8+2j), 6]


    > Define your own ordering if you need to sort incomparable types.


    Yes, key= lets you sort anything anyway you want.
    >>> l=[1, '2', 3j]
    >>> sorted(l, key = str)

    [1, '2', 3j]
    >>> sorted(l, key = id)

    ['2', 3j, 1]
     
    Terry Reedy, Nov 9, 2008
    #7
  8. walterbyrd

    Terry Reedy Guest

    walterbyrd wrote:

    Guido and the developers changed the behavior of order comparisons, and
    hence of sorts, because they agreed, on the basis of person-decades of
    experience, with no dissent that I know of, that the new behavior would
    be better.

    Have you written any Python code where you really wanted the old,
    unpredictable behavior?

    > Would it be better if python lists only accepted one type of data?


    Take a look at the array module.
     
    Terry Reedy, Nov 9, 2008
    #8
  9. walterbyrd

    Kay Schluehr Guest

    On 9 Nov., 05:04, Terry Reedy <> wrote:

    > Have you written any Python code where you really wanted the old,
    > unpredictable behavior?


    Sure:

    if len(L1) == len(L2):
    return sorted(L1) == sorted(L2) # check whether two lists contain
    the same elements
    else:
    return False

    It doesn't really matter here what the result of the sorts actually is
    as long as the algorithm leads to the same result for all permutations
    on L1 ( and L2 ).
     
    Kay Schluehr, Nov 9, 2008
    #9
  10. On Sat, 08 Nov 2008 19:06:14 -0800, walterbyrd wrote:

    > On Nov 8, 7:44 pm, Steven D'Aprano <st...@REMOVE-THIS-
    > cybersource.com.au> wrote:
    >
    >> Define your own ordering if you need to sort incomparable types.

    >
    > If you starting new, I suppose you can always work around this new
    > enhancement. But, couldn't this cause a lot of backward compatibility
    > issues?


    Which is why the change has only been introduced into Python 3, and not
    Python 2.x.


    > Also, I thought that part of the python philosophy was to allow any sort
    > of object in a list, and to allow the same methods to work with whatever
    > was in list.


    You wouldn't expect this to work would you?

    sum( [1, 2, None, "a string", {'x': 5}, []] )

    You can only sum objects which are compatible. You can only sort objects
    which define an order: you can't sort lists containing complex numbers
    because "greater than" and "less than" aren't defined for complex
    numbers, and in Python 3 you will no longer be able to order mixed
    objects unless they are intrinsically comparable (e.g. floats and ints),
    unless you define your own order.



    --
    Steven
     
    Steven D'Aprano, Nov 9, 2008
    #10
  11. walterbyrd

    Kay Schluehr Guest

    On 9 Nov., 05:49, Alex_Gaynor <> wrote:
    > On Nov 8, 11:36 pm, Kay Schluehr <> wrote:
    >
    >
    >
    > > On 9 Nov., 05:04, Terry Reedy <> wrote:

    >
    > > > Have you written any Python code where you really wanted the old,
    > > > unpredictable behavior?

    >
    > > Sure:

    >
    > > if len(L1) == len(L2):
    > > return sorted(L1) == sorted(L2) # check whether two lists contain
    > > the same elements
    > > else:
    > > return False

    >
    > > It doesn't really matter here what the result of the sorts actually is
    > > as long as the algorithm leads to the same result for all permutations
    > > on L1 ( and L2 ).

    >
    > that same thing could be done with a multiset type, which would also
    > have better performance(O(n) vs. O(nlogn)).


    I guess building a multiset is a little more expensive than just O(n).
    It is rather like building a dict from a list which is O(k*n) with a
    constant but small factor k. The comparison is of the same order. To
    enable the same behavior as the applied sorted() a multiset must
    permit unhashable elements. dicts don't do the job.
     
    Kay Schluehr, Nov 9, 2008
    #11
  12. On Sat, 08 Nov 2008 20:36:59 -0800, Kay Schluehr wrote:

    > On 9 Nov., 05:04, Terry Reedy <> wrote:
    >
    >> Have you written any Python code where you really wanted the old,
    >> unpredictable behavior?

    >
    > Sure:
    >
    > if len(L1) == len(L2):
    > return sorted(L1) == sorted(L2) # check whether two lists contain
    > the same elements
    > else:
    > return False
    >
    > It doesn't really matter here what the result of the sorts actually is
    > as long as the algorithm leads to the same result for all permutations
    > on L1 ( and L2 ).


    How often do you care about equality ignoring order for lists containing
    arbitrary, heterogeneous types?

    In any case, the above doesn't work now, since either L1 or L2 might
    contain complex numbers. The sorted() trick only works because you're
    making an assumption about the kinds of things in the lists. If you want
    to be completely general, the above solution isn't guaranteed to work.

    If you're prepared to assume hashability, then the obvious Multiset
    solution is probably better even than the above. If you want complete
    generality, you can't even assume that items in the list can be ordered
    at all, so you need something like this:


    def collate_and_sort(L):
    D = {}
    for item in L:
    t = type(item)
    x = D.setdefault(t, [])
    x.append(item)
    for x in D.values():
    try:
    x.sort()
    except TypeError:
    try:
    x.sort(key=str)
    except TypeError:
    x.sort(key=id)
    return D


    def unordered_equals(L1, L2):
    if len(L1) != len(L2):
    return False
    try:
    return sorted(L1) == sorted(L2)
    except TypeError:
    return collate_and_sort(L1) == collate_and_sort(L2)


    But note that even this solution isn't perfect, since it will fail to do
    the right thing for L1=[1, {}, 2] and L2=[1, {}, 2.0]. Here is a way to
    solve the problem assuming only that the items support equality:

    def unordered_equals2(L1, L2):
    if len(L1) != len(L2):
    return False
    for item in L1:
    if L1.count(item) != L2.count(item):
    return False
    return True


    --
    Steven
     
    Steven D'Aprano, Nov 9, 2008
    #12
  13. walterbyrd

    Kay Schluehr Guest

    On 9 Nov., 07:06, Steven D'Aprano <st...@REMOVE-THIS-
    cybersource.com.au> wrote:
    > On Sat, 08 Nov 2008 20:36:59 -0800, Kay Schluehr wrote:
    > > On 9 Nov., 05:04, Terry Reedy <> wrote:

    >
    > >> Have you written any Python code where you really wanted the old,
    > >> unpredictable behavior?

    >
    > > Sure:

    >
    > > if len(L1) == len(L2):
    > > return sorted(L1) == sorted(L2) # check whether two lists contain
    > > the same elements
    > > else:
    > > return False

    >
    > > It doesn't really matter here what the result of the sorts actually is
    > > as long as the algorithm leads to the same result for all permutations
    > > on L1 ( and L2 ).

    >
    > How often do you care about equality ignoring order for lists containing
    > arbitrary, heterogeneous types?


    A few times. Why do you care, Steven?

    > In any case, the above doesn't work now, since either L1 or L2 might
    > contain complex numbers.
    > The sorted() trick only works because you're
    > making an assumption about the kinds of things in the lists. If you want
    > to be completely general, the above solution isn't guaranteed to work.


    You are right. I never used complex numbers in Python so problems were
    not visible. Otherwise the following comp function in Python 2.X does
    the job:

    def comp(x1, x2):
    try:
    if x1<x2:
    return -1
    else:
    return 1
    except TypeError:
    if str(x1)<str(x2):
    return -1
    else:
    return 1

    Not sure how to transform it into a search key that is efficient and
    reliable.

    [...]

    > Here is a way to
    > solve the problem assuming only that the items support equality:
    >
    > def unordered_equals2(L1, L2):
    > if len(L1) != len(L2):
    > return False
    > for item in L1:
    > if L1.count(item) != L2.count(item):
    > return False
    > return True


    Which is O(n**2) as you might have noted.
     
    Kay Schluehr, Nov 9, 2008
    #13
  14. On Sat, 08 Nov 2008 22:53:14 -0800, Kay Schluehr wrote:

    >> How often do you care about equality ignoring order for lists
    >> containing arbitrary, heterogeneous types?

    >
    > A few times. Why do you care, Steven?


    I'm a very caring kind of guy.


    >> In any case, the above doesn't work now, since either L1 or L2 might
    >> contain complex numbers.
    >> The sorted() trick only works because you're making an assumption about
    >> the kinds of things in the lists. If you want to be completely general,
    >> the above solution isn't guaranteed to work.

    >
    > You are right. I never used complex numbers in Python so problems were
    > not visible. Otherwise the following comp function in Python 2.X does
    > the job:

    [...]
    > Not sure how to transform it into a search key that is efficient and
    > reliable.


    Yes, that's a general problem. It's not always easy to convert a sort
    comparison function into a key-based sort. I know that 99% of the time
    key is the right way to do custom sorts, but what about the other 1%?


    > [...]
    >
    >> Here is a way to
    >> solve the problem assuming only that the items support equality:
    >>
    >> def unordered_equals2(L1, L2):
    >> if len(L1) != len(L2):
    >> return False
    >> for item in L1:
    >> if L1.count(item) != L2.count(item):
    >> return False
    >> return True

    >
    > Which is O(n**2) as you might have noted.


    Yes, I did notice. If you can't assume even ordering, then you need to do
    a lot more work.


    --
    Steven
     
    Steven D'Aprano, Nov 9, 2008
    #14
  15. Kay Schluehr <> writes:

    > On 9 Nov., 07:06, Steven D'Aprano <st...@REMOVE-THIS-

    [...]
    >> In any case, the above doesn't work now, since either L1 or L2 might
    >> contain complex numbers.
    >> The sorted() trick only works because you're
    >> making an assumption about the kinds of things in the lists. If you want
    >> to be completely general, the above solution isn't guaranteed to work.

    >
    > You are right. I never used complex numbers in Python so problems were
    > not visible. Otherwise the following comp function in Python 2.X does
    > the job:
    >
    > def comp(x1, x2):
    > try:
    > if x1<x2:
    > return -1
    > else:
    > return 1
    > except TypeError:
    > if str(x1)<str(x2):
    > return -1
    > else:
    > return 1
    >


    Sadly it fails on transitivity:

    >>> comp(2, 3j)

    -1
    >>> comp(3j, True)

    -1
    >>> comp(True, 2)

    -1

    --
    Arnaud
     
    Arnaud Delobelle, Nov 9, 2008
    #15
  16. On Nov 8, 10:14 pm, Kay Schluehr <> wrote:
    > I guess building a multiset is a little more expensive than just O(n).
    > It is rather like building a dict from a list which is O(k*n) with a
    > constant but small factor k. The comparison is of the same order. To
    > enable the same behavior as the applied sorted() a multiset must
    > permit unhashable elements. dicts don't do the job.


    Although it has a runtime of k*n, it is still O(n). big-O notation
    ignores constant factors, dealing only with scalability.
     
    Rhamphoryncus, Nov 9, 2008
    #16
  17. Kay Schluehr wrote:
    > On 9 Nov., 07:06, Steven D'Aprano <st...@REMOVE-THIS-
    > cybersource.com.au> wrote:
    >> How often do you care about equality ignoring order for lists containing
    >> arbitrary, heterogeneous types?

    >
    > A few times. Why do you care, Steven?


    "I miss this feature" is an unqualified statement, just like "I'll miss George
    W. Bush". That does not necessarily imply that I want him back in the position
    that the had for the last eight years. It might just mean that it was fun to
    see him on telly (although I bet his entertainment show was more expensive
    than the average Marx-Brothers sketch).

    Stefan
     
    Stefan Behnel, Nov 9, 2008
    #17
  18. walterbyrd

    Kay Schluehr Guest

    On 9 Nov., 09:26, Rhamphoryncus <> wrote:
    > On Nov 8, 10:14 pm, Kay Schluehr <> wrote:
    >
    > > I guess building a multiset is a little more expensive than just O(n).
    > > It is rather like building a dict from a list which is O(k*n) with a
    > > constant but small factor k. The comparison is of the same order. To
    > > enable the same behavior as the applied sorted() a multiset must
    > > permit unhashable elements. dicts don't do the job.

    >
    > Although it has a runtime of k*n, it is still O(n).  big-O notation
    > ignores constant factors, dealing only with scalability.


    You are right. I remembered this short after my posting was sent.
     
    Kay Schluehr, Nov 9, 2008
    #18
  19. walterbyrd

    Roy Smith Guest

    In article <>,
    Terry Reedy <> wrote:

    > Yes, key= lets you sort anything anyway you want.
    > >>> l=[1, '2', 3j]
    > >>> sorted(l, key = str)

    > [1, '2', 3j]


    The problem here is that str() is degenerate, i.e. a != b does not imply
    str(a) != str(b).

    > >>> sorted(l, key = id)

    > ['2', 3j, 1]


    And of course, this has to opposite problem, a == b does not imply id(a) ==
    id(b). Whether either of these "problems" is really a problem obviously
    depends on what you're trying to do.

    In 3.0, can you still order types? In 2.x, you can do:

    >>> t1 = type(1)
    >>> t2 = type(1j)
    >>> t1 < t2

    False

    If this still works in 3.0, then you can easily do something like:

    def total_order(o1, o2):
    "Compare any two objects of arbitrary types"
    try:
    return o1 <= o2
    except UncomparableTypesError: # whatever the right name is
    return type(o1) <= type(o2)

    and get the same effect as you had in 2.x.
     
    Roy Smith, Nov 9, 2008
    #19
  20. >
    > Also, I thought that part of the python philosophy was to allow any
    > sort of object in a list, and to allow the same methods to work with
    > whatever was in list.


    Not really. When the usual argument about the existence (and
    justification) of lists & tuples comes along, one common distinction is
    that

    - tuples contain arbitrary object of varying types, so they are kind
    of "records"
    - lists should contain uniform objects.

    None of this is enforced, but it's good customs to do so & to put it
    frankly: if I came along a piece of code that created a list like the
    one you presented, I'd say it's a code-smell.

    Diez
     
    Diez B. Roggisch, Nov 9, 2008
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Siemel Naran

    Does true ^ true return false?

    Siemel Naran, Jun 17, 2004, in forum: C++
    Replies:
    19
    Views:
    700
    Chris Theis
    Jun 18, 2004
  2. Chip
    Replies:
    6
    Views:
    2,689
    E. Robert Tisdale
    Jan 8, 2005
  3. Andy Leszczynski
    Replies:
    4
    Views:
    349
    Erik Max Francis
    Oct 13, 2005
  4. Pierre Quentel

    "0 in [True,False]" returns True

    Pierre Quentel, Dec 12, 2005, in forum: Python
    Replies:
    59
    Views:
    1,075
    Grant Edwards
    Dec 16, 2005
  5. bdb112
    Replies:
    45
    Views:
    1,417
    jazbees
    Apr 29, 2009
Loading...

Share This Page