10

I wanted to create a simple binary tree as followed by this image:

http://imgur.com/QCVSW.png

basically empty , but the last values so I created the root list :

root = [list(),list()]

and made a recursive function to populate it all :

def TF(nodeT,nodeF , i):
    if i == 35 : return 'done'

    TF(nodeT.append([]),nodeT.append([]) , i = i + 1) #append T , F in the true node
    TF(nodeF.append([]),nodeT.append([]) , i = i + 1) #append T , F in the false node

my problem is simple list.append(something) in python return "None" so as soon as the function get called again (TF(None,None,1)) None.append doesnt exists.

how do I solve this? thanks in advance.

also if you have any suggestion on how to make this more efficient or in another way (never got to test my code so I am not sure on how it will do)

(my final goal is to have a True False map and an argument so : "FTFTFFFTFTF" will bring up the letter "M" etc ...)

Emre Erkan
  • 8,433
  • 3
  • 48
  • 53
Lior Co
  • 109
  • 1
  • 1
  • 3
  • 2
    Would you elaborate on the use of this? – Hamish Grubijan Dec 16 '09 at 22:38
  • 3
    Please do not transliterate code from other languages into Python. Please try to think about how Python actually works; please think about how the algorithm actually works. Then -- after understanding -- write the Python. Simply replace C-language tokens with Python tokens will rarely give you working Python. – S.Lott Dec 17 '09 at 12:50
  • 3
    This is one of the things I detest about python, and IMO, is completely unpythonic. Any method that mutates `self` should return `self`. Any function that mutates anything should return that thing. – DylanYoung Oct 03 '16 at 18:26
  • 1
    I've upvoted DylanYoung, but I'd rephrase as follows: Having methods that mutate `self` returning `self` allows chaining and assignation in a more semantic and readable way, contributing to the language's expressive power. It's something I'd definitely would like to see in python! – nandilugio Oct 15 '19 at 13:05
  • `python` bad design strikes again – WestCoastProjects Mar 15 '20 at 06:07

7 Answers7

30

In python you can use the "+" operator to contatenate two lists leaving the originals untouched. I guess that's what you want to do according to your question title. Thus

[1, 2] + [3] 

will return

[1, 2, 3]

so you can use it more in a "functional fashion". Just in case you need it

[1, 2].__add__([3])

is the equivalent to the expression before.

csierra
  • 1,010
  • 10
  • 8
  • This is the most correct answer wrt OP original intent. Adding more code for first making assignment and then returning the referernce is unnecessary boilerplate. Btw is there an equivalent for returning the result of `.extend()` ? – WestCoastProjects May 07 '17 at 01:12
  • 1
    as far as I understands `.extend()` is equivalent to `+` or `__add__` but it alters the list in place. When you want to leave the originals untouched don't use `extend()`. – csierra May 08 '17 at 06:19
20

To solve your exact question, you can do this:

def list_append(lst, item):
  lst.append(item)
  return lst

and then list_append(lst, item) will append item to the lst and then return the lst.

Peter
  • 127,331
  • 53
  • 180
  • 211
  • And this same pattern has to be repeated for every mutation method.. I'm considering how to make a subclass of `list` that would just have these `python` idiosyncracies covered up. – WestCoastProjects Mar 15 '20 at 06:15
4

Dont append to the list, create them. Python has custom data structures btw :P

class BinTree(object):
    def __init__(self, left=None, right=None):
        self.left = left
        self.right = right
    def __str__(self):
        return " (%s, %s) " % (self.left, self.right)

def maketree( depth ):
    if depth == 0:
        return BinTree( True, False )
    return BinTree(
        maketree( depth-1 ),
        maketree( depth-1 ))

print maketree( 4 )

If you really, really want lists then replace BinTree( x, y ) with [x,y]

Jochen Ritzel
  • 104,512
  • 31
  • 200
  • 194
3

You can append first and then pass the reference:

nodeT.append([])
TF(nodeT, nodeT, i + 1)

But your function makes no sense to me. Even if it did make sense, it would cause 2**35 function calls to TF, which would take rather a long time to complete.

Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
2

Adding to @csierra 's answer - which I upvoted as the most directly answring the OP: the

+  [a,b]

(with single bracket around the addend) is like list.extend([a,b])

       [ 1, 2, 3,4]  + [5,6]

Out[6]: [1, 2, 3, 4, 5, 6]

Whereas

+  [[a,b]]

(with double brackets) is like list.append([a,b])

In [5]:      [ 1, 2, 3,4]  + [[5,6]]
Out[5]: [1, 2, 3, 4, [5, 6]]
WestCoastProjects
  • 58,982
  • 91
  • 316
  • 560
1

There's a better way to create a binary tree, but I could not understand what you want to do with it.

Here is the code:

>>> def tree(i):
    if i == 0:
        return ['T', 'F']
    return [tree(i-1), tree(i-1)]

>>> tree(3)
[[[['T', 'F'], ['T', 'F']], [['T', 'F'], ['T', 'F']]], [[['T', 'F'], ['T', 'F']], [['T', 'F'], ['T', 'F']]]]
jbochi
  • 28,816
  • 16
  • 73
  • 90
1

Well although the answers above me are correct, another nice(yet maybe not pretty) way to do that would be using the fact that append returns None:

func(l.append([]) is None and l[-1])

Which practically let's you do whatever you want in the same line with .append

user3848844
  • 509
  • 6
  • 20