Confusing […] List in Python: What is it?

前端 未结 9 2021
傲寒
傲寒 2020-11-29 10:52

So I was writing up a simple binary tree in Python and came across [...]

I don\'t believe this to be related to the Ellipsis object, more it seems to have something

相关标签:
9条回答
  • 2020-11-29 11:32

    The issue is because one of the list element is referencing the list itself. So if an attempt to print all the elements is made then it would never end.

    Illustration:

    x = range(3)
    x.append(x)
    x[3][3][3][3][3][0] = 5
    print x
    

    Output:

    [5, 1, 2, [...]]
    

    x[3] is a referring to x itself. Same goes for x[3][3].

    This can be visualized better here

    0 讨论(0)
  • 2020-11-29 11:33

    If you would have used a PrettyPrinter, the output would had been self explanatory

    >>> l = [1,2,3,4]
    >>> l[0]=l
    >>> l
    [[...], 2, 3, 4]
    >>> pp = pprint.PrettyPrinter(indent = 4)
    >>> pp.pprint(l)
    [<Recursion on list with id=70327632>, 2, 3, 4]
    >>> id(l)
    70327632
    

    In other words its something like

    enter image description here

    0 讨论(0)
  • 2020-11-29 11:35

    EDIT: As mentioned above, this isn't the Ellipsis object, but the result of a looped list. I jumped the gun here. Knowing about the Ellipsis object is a good bit of back shelf knowledge should you find an Ellipsis in some actual code, rather than the output.


    The Ellipsis object in Python is used for extended slice notation. It's not used in current Python core libraries, but is available for developers to define in their own libraries. For example, NumPy (or SciPy) use this as part of their array object. You'll need to look at the documentation for tree() to know exactly how Ellipsis behaves in this object.

    From Python documentation:

    3.11.8 The Ellipsis Object

    This object is used by extended slice notation (see the Python Reference Manual). It supports no special operations. There is exactly one ellipsis object, named Ellipsis (a built-in name).

    It is written as Ellipsis.

    0 讨论(0)
  • 2020-11-29 11:45

    I believe, that your 'tree' contains itself, therefore it contains cycles.

    Try this code:

       a = [1,2,3,4]
       print a
       a.append(a)
       print a
    

    The first print outputs:

      [1,2,3,4]
    

    while the second:

      [1,2,3,4, [...]]
     

    The reason is using

     def Keys(x,y=[]):
     
    This is wrong and evil. List is a mutable object, and when used as a default parameter, it is preserved between function calls. So each y += "anything" operation adds to the same list (in all function calls, and since the function is recursive...)


    See the Effbot or Devshed for more details on mutable objects passed as default values for functions.

    0 讨论(0)
  • 2020-11-29 11:45

    I don't believe this to be related to the Ellipsis object, more it seems to have something to do with an infinity loop (due to Python's shallow copy?). The source of this infinity loop and why it doesn't get expanded while expanding when accessed is something I'm completely lost to, however

    Look at the following code:

    >>> a = [0]
    >>> a.append(a)
    >>> print a
    [0, [...]]
    

    How is Python supposed to print a? It is a list that contains a zero and a reference to itself. Hence it is a list that contains a zero and a reference to a list

    [0, [...]]
    

    which in turn contains a zero and a reference to a list

    [0, [0, [...]]]
    

    which in turn contains a zero and a reference to a list, and so on, recursively:

    [0, [0, [0, [...]]]]
    [0, [0, [0, [0, [...]]]]]
    [0, [0, [0, [0, [0, [...]]]]]]
    ...
    

    There is nothing wrong with the recursive data structure itself. The only problem is that it cannot be displayed, for this would imply an infinite recursion. Hence Python stops at the first recursion step and deals with the infinity issue printing only the ellipsis, as was pointed out in previous answers.

    0 讨论(0)
  • 2020-11-29 11:45

    For the difference between the two versions of the function Keys, note the following difference:

    y+=[x[2]]+Keys(x[0],y)+Keys(x[1],y)
    

    The right side value in this statement is a list which contains x[2], plus the ELEMENTS OF Keys(x[0],y) and the ELEMENTS OF Keys(x[1],y)

    y+=[x[2],Keys(x[0],y),Keys(x[1],y)]
    

    The right side value in this statement is a list which contains x[2], plus the LIST Keys(x[2],y) and the LIST Keys(x[1],y).

    So the version using [a,b] will causing y contains itself as its elements.

    Some other notes:

    1. Since in python, the default value object is created once when the function is defined, the first version will not work like the example shows. It will contain multiple copy of some keys. It's hard to explain in short, but you can get some idea by printing the values of x, y on each call of Keys.

      This is confirmed by running the function on my machine with python 2.5.2.

    2. Also because the default value is defined only once at function definition time, even the function works correct for the first time, it will not work when calling with a different a, since the keys in the first binary tree will remain in y.

      You can see this by calling Keys(a) twice, or calling it on two different lists.

    3. The second parameter is not required for this problem. The function can be like this:

      def Keys(a): if a = []: return [] else: return [a[2]]+Keys(a[0])+Keys(a[1])

      Defining a recursive function basically contains two part, solve subproblems and combined the results. In your code, the combining results part is repeated twice: one by accumulating them in y, one by adding the list together.

    0 讨论(0)
提交回复
热议问题