Question Authors' Forum

Exercice : Adding a method to a class

Picture of philippe juhel
Exercice : Adding a method to a class
by philippe juhel - Tuesday, 15 March 2016, 12:44 AM


I want to ask this question in a Moodle test : 

Given this following Python code, add the missing code to have the following output : 

I have 4 wheels

The code given to the students is :

class Car:
    def __str__(self):
        return "I have " + str(self.nbWheels) + " wheels"
c = Car(4)

The missing code is the constructor so I expect this response : 

def __init__(self,nbOfWheels):
  self.nbWheels = nbOfWheels

I use this template : 

class Car:
    def __str__(self):
        return "I have " + str(self.nbWheels) + " wheels"
c = Car(4)

But when I test this question and add the code of the constructor, I get this error : 

Syntax Error(s)

Sorry: IndentationError: expected an indented block (prog.python3, line 3)
Where should I put the {{STUDENT_ANSWER}} in the template to solve the problem of indentation?

Best reagrds,


Picture of Richard Lobb
Re: Exercice : Adding a method to a class
by Richard Lobb - Tuesday, 15 March 2016, 10:00 AM

Hi Phillipe

Usually I ask this sort of question in a way that requires the student to paste the entire class into the answer box. That avoid indentation hassles and if the student's answer is wrong it's easier for them and the tutors to see why.

However, you can write questions like this (and I used to do so when converting old written exams into a CodeRunner format) by writing extra code in the template that indents the student code to the required level, leaving it untouched if it's already correctly indented.

Here's what I think you had in mind:

Screen dump of missing init method question

The template for that is the following:

import sys

def __indent_line(line, extra_space):
    """Add the given amount of extra space at the start (or remove, if negative)"""
    if extra_space >= 0:
        return extra_space * ' ' + line
    elif len(line) - len(line.lstrip()) >= -extra_space:
        return line[extra_space + 1 : ]
        raise Exception("Line '{}' has a negative indent!".format(line))

def __indent(code, num_spaces):
    """Indent the given code by some fixed amount such that the first non-blank
       line has 'num_spaces' spaces at the start.
    lines = code.split('\n')
    non_empty_lines = [line for line in lines if line != '']
    if non_empty_lines:
        first = non_empty_lines[0]
        current_indent =  len(first) - len(first.lstrip())
        reqd_indent = num_spaces - current_indent
        indented_lines = [__indent_line(line, reqd_indent) for line in lines]
        return '\n'.join(indented_lines) + '\n'
        return code  # Empty

__skeleton__ = """class Car:
    def __str__(self):
        return "I have " + str(self.nbWheels) + " wheels"
{0}  # Student code inserted here

__student_answer__ = """{{ STUDENT_ANSWER | e('py') }}"""
    __indented__answer__ = __indent(__student_answer__, 4)
except Exception as e:
    print(e, file=sys.stderr)
    exec(__skeleton__.format(__indented__answer__) + '\n' + """{{ TEST.testcode | e('py') }}""")

Of course, what's really need with questions of this sort is a way to pre-load the Ace-editor answer box with the skeleton code and write-protect all but the sections the student is allowed to alter. This is on my todo list, but you'll probably have to wait till the end of the year for that. Or later :-)


Picture of philippe juhel
Re: Exercice : Adding a method to a class
by philippe juhel - Wednesday, 16 March 2016, 3:07 AM

Thank you for your reply. 

Both solutions work.

Best regards,