#!/usr/bin/env python # coding: utf-8 # In[4]: xml=""" How many items in a list? Write a function how_many(list_in) which returns the number of items in list_in.


]]>
len() returns the length (the number of items) of an object. The argument may be a sequence (such as a string, bytes, tuple, list, or range) or a collection (such as a dictionary, set, or frozen set).

]]>
1 0 0 python3 0 1 10, 20, ... 0 0 6 100 def how_many(list_in): '''returns the number of elements in list_in''' def how_many(list_in): '''returns the number of elements in list_in''' return len(list_in) 1 1 0 0 0 10240 1 print ( how_many(['fig', 'kiwi', 13.7])) 3 SHOW print(how_many([])) 0 SHOW print(how_many([' '])) 1 SHOW print(how_many([['only', 'count'], ['the' 'top'], ['level', 'lists']])) 3 SHOW print(how_many([1, [2, 3, [4, 5], 6], 7])) 3 SHOW
""" # In[5]: import xml.etree.ElementTree as ET root = ET.fromstring(xml) root # In[7]: root.tag # In[9]: for child in root: print(child.tag, child.attrib) for gchild in child: print(gchild.tag, gchild.attrib) # In[31]: from IPython.display import HTML for question in root.findall('question'): display(HTML(question.find('questiontext/text').text)) answer = question.find('answer').text print(answer) print() tests = question.find('testcases') for test in tests.findall('testcase'): print(test.find('testcode/text').text, test.find('expected/text').text) # There are a couple of ways we can evaluate the code represented by the string, specifically using `eval()` or `exec()`. # # - `exec()` doesn't return anything; # - `eval()` returns the final value; # In[32]: exec(answer) # In[33]: how_many(['fig', 'kiwi', 13.7]) # In[122]: get_ipython().run_cell_magic('capture', 'my_answer --no-stderr', "answers = []\nfor question in root.findall('question'):\n tests = question.find('testcases')\n for test in tests.findall('testcase'):\n exec(test.find('testcode/text').text)\n answers.append(test.find('expected/text').text)\n") # The way the question is written and handled is really shonky... I suspect it gives all sorts of opportunities for false somethings?! # In[124]: my_answer.stdout, '\n'.join(answers)+'\n' # In[57]: my_answer.stdout, '\n'.join(answers)+'\n' # If we try to do some simple assertion tests on evaluated code, things all go wrong... we need to to type checking, white space clearning (nut might whitespace be important?) etc etc. # In[121]: import re for question in root.findall('question'): tests = question.find('testcases') for test in tests.findall('testcase'): _test = test.find('testcode/text').text print(_test, '..') matches = re.findall(r"print\s*\(\s*(.*)\s*\)", _test) if matches: print(matches[0]) answer = eval(matches[0]) #Hack the assertion so tests pass - this leads to a loss of information # and suggests there's something wrong with how answers are represented? assert str(answer) == test.find('expected/text').text.strip() # ## Addenda - Possibly Useful Fragments # In[112]: #The following replicates the %%capture #https://stackoverflow.com/a/3906309/454773 import sys from io import StringIO import contextlib @contextlib.contextmanager def stdoutIO(stdout=None): old = sys.stdout if stdout is None: stdout = StringIO() sys.stdout = stdout yield stdout sys.stdout = old with stdoutIO() as s: exec('print("hello")') s.getvalue()