2

With assignment expression, I thought I could try list comprehension to create Fibonacci. I first initialize a Fibonacci list of 5 elements f = [1,2,3,4,5] with the first two values being the seeds. The test run below shows the assignment expression works.

[y := f[n-1] + f[n-2] for n in range(2,6)] 
[3, 5, 7, 9]

But the real Fibonacci failed at f[n] where a red marker showed in Python shell.

[f[n] := f[n-1] + f[n-2] for n in range(2,6)] 

Is it because the f[n] is not a valid variable name?
Does that mean assignment expression might not help in list comprehension for Fibonacci?

Almog
  • 437
  • 1
  • 3
  • 10
Leon Chang
  • 335
  • 2
  • 6
  • 4
    Assignment expressions were added recently in Python 3.8. Make sure the language level of your IDE is set to this. – Barmar Oct 27 '20 at 05:45
  • 1
    Your fibonacci expression is not correct, it seems like you're only generating odd numbers. Try `s = [0, 1]; result = s + [(s := [s[1], s[0] + s[1]]) and s[1] for k in range(10)]` – cs95 Oct 27 '20 at 06:02
  • 2
    Did you look at the error message you got? It says "SyntaxError: cannot use assignment expressions with subscript". Thus, you cannot use assignment expressions to update an element of a list, as you try. – JohanL Oct 27 '20 at 06:10
  • 1
    I would like to argue that this is **not** a duplicate as currently set, since this is a question about the assignment operator, rather than the Fibonacci sequence. The latter is more of an example. – JohanL Oct 27 '20 at 06:13
  • Thanks for all the replies. As @cs95 suggested, `f = [0, 1]; f += [(f := [f[1], f[0] + f[1]]) and f[1] for n in range(10)]` works without needing f[n] :=. By the way, I am using the IDE PyCharm with Python3.8, When I hovered over the red marker, it showed 'identifier expected'. How do I get the error message "SyntaxError ..."? – Leon Chang Oct 28 '20 at 03:53

3 Answers3

1

Using [f[n] := ... results in SyntaxError: cannot use assignment expressions with subscript, so clearly this restriction prevents doing it that way. This is mentioned in PEP 572 in a section titled Differences between assignment expressions and assignment statements where is says

  • Single assignment targets other than a single NAME are not supported.
martineau
  • 99,260
  • 22
  • 139
  • 249
0

Just to show some methods of generating a Fibonacci.py series that I know of:

class   Fib:

    def __init__(self, *f01):
        self.f0, self.f1 = f01

    # Calculate the n-th item of the Fibonacci series
    def fibRecursive(self, n):
        if n == 0:
            return self.f0
        elif n == 1:
            return self.f1
        return self.fibRecursive(n-2) + self.fibRecursive(n-1)

    def fibAppend(self, n):
        f = [self.f0, self.f1]
        for i in range(2, n):
            f.append(f[i-2]+f[i-1])
        return f

    def fibYield(self, n):
        x, y = self.f0, self.f1
        for _ in range(n):
            yield x
            x, y = y, x + y

    def fibIncremental(self, n):
        x, y = self.f0, self.f1
        f = [x, y]
        for i in range(2, n):
            x, y = y, x + y
            f.append(y)
        return f

    def fibLCAE(self, n):   # LC with Assignment expression
        f = [self.f0, self.f1]
        f += [(f := [f[1], f[0] + f[1]]) and f[1] for i in range(2,n)]
        return f

if  __name__ == '__main__':
    n = int(input("How many numbers in the Fibonacci sequence?   "))
    fd = Fib.__dict__
    for f in [Fib(0, 1), Fib(3, -3), Fib(-50, 100)]:
        print(f'Fibonacci initial two numbers : {f.f0}, {f.f1}')
        for func in [fd['fibAppend'], fd['fibIncremental'], fd['fibLCAE']]:
            print(func(f, n))
        print([f.fibRecursive(i) for i in range(n)])
        print(list(f.fibYield(n)))
        print()

>>> python.exe Fibonacci.py
How many numbers in the Fibonacci sequence?   13
Fibonacci initial two numbers : 0, 1
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]
....
Fibonacci initial two numbers : 3, -3
[3, -3, 0, -3, -3, -6, -9, -15, -24, -39, -63, -102, -165]
....
Fibonacci initial two numbers : -50, 100
[-50, 100, 50, 150, 200, 350, 550, 900, 1450, 2350, 3800, 6150, 9950]
....
Leon Chang
  • 335
  • 2
  • 6
0

How about two list comprehensions, or build a base list, then compute?

Generate fibonacci base array,

fb = [n for n in range(0,21)]
# or
fb = [0] + [1] * 20

Calculate fib(13), (want: [f[n] := f[n-1] + f[n-2] for n in range(2,20)])

f = [ fib(fb,n) for n in range(2,20) ]

Where fib(f,n) is:

def fib(f,n):
    if n > 1:
        f[n] = f[n-1] + f[n-2]
    return f[n]

Fibonacci sequence:

fb[0:13]: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]
fib(fb,13-1) = 144
ChuckCottrill
  • 3,999
  • 2
  • 22
  • 34