Pascal's Triangle Generator in Python
def chunk_adder(lst):
  for i in lst:
    if len(i) == 1:
      yield i[0]
    else:
      yield sum(i)



sum can happilly consume iterable of size 1, it can even consume iterable of size 0:

&gt;&gt;&gt; sum([1])
1
&gt;&gt;&gt; sum([])
0


So you can simplify it to:

def chunck_adder(iterable):
    for element in iterable:
        yield sum(element)


Which is simply

def chunck_adder(iterable):
    yield from map(sum, iterable)


So you could simplify pascal_next instead:

def pascal_next(lst):
    return list(map(sum, double_chunker(lst)))





def double_chunker(lst):
  leng = len(lst)
  for i in range(leng):
    if i == 0:
      yield [lst[0]]
    elif i == 1:
      yield [lst[0], lst[1]]
    elif i == leng:
      yield [lst[-1]]
    else:
      yield [lst[i-1], lst[i]]
  yield [lst[-1]]



The intent is pretty much the same than the pairwise recipe from itertools. Except you want to yield the first and last element as well.

Here you have two possibilities:


either yield them manually:

import itertools

def double_chunker(lst):
    if not lst:
        return
    a, b = itertools.tee(lst)
    next(b, None)

    yield [lst[0]]
    yield from zip(a, b)
    yield [lst[-1]]


But this forces the argument to be a list, or at least to know if its empty and to implement __getitem__.
or add boundary values to your input so pairwise can work properly:

import itertools


def pairwise(iterable):
    a, b = itertools.tee(iterable)
    next(b, None)
    return zip(a, b)


def double_chuncker(iterable):
    extended = itertools.chain([0], iterable, [0])
    return pairwise(extended)


Which I recommend because it happily consume any iterable.





def pascal_triangle(rows):
  end = [[1]]
  for i in range(rows):
    end.append(pascal_next(end[-1]))
  return end



Instead of relying on the list being constructed, I would explicitly store the current row. I would also turn this into an infinite generator because it really is and maybe provide an helper function for convenience:

def pascal_triangle():
    row = [1]
    while True:
        yield row
        row = pascal_next(row)


def pascal_triangle_up_to(n):
    return list(itertools.islice(pascal_triangle(), n))




Full code:

import itertools


def pairwise(iterable):
    a, b = itertools.tee(iterable)
    next(b, None)
    return zip(a, b)


def double_chuncker(iterable):
    extended = itertools.chain([0], iterable, [0])
    return pairwise(extended)


def pascal_next(iterable):
    return list(map(sum, double_chuncker(iterable)))


def pascal_triangle():
    row = [1]
    while True:
        yield row
        row = pascal_next(row)


def pascal_triangle_up_to(n):
    return list(itertools.islice(pascal_triangle(), n))


if __name__ == '__main__':
    # Testing
    for row in pascal_triangle():
        print(row, end='')
        if (input()):
            break