代做ELEC0021 Programming 2023-24代写留学生Python程序
- 首页 >> C/C++编程ELEC0021 Programming 2023-24
1st PROGRAMMING ASSIGNMENT – Part 1A
Virtual Dice Throwing
This is an introductory programming exercise in order to refresh your last year’s knowledge of programming and get you introduced to Python. The program to write should emulate virtual dice throwing. It should get from the keyboard the number of sides of the virtual dice and the number of times to be thrown, the latter should be a multiple of the number of sides. The program should then throw the dice and print out the number of times each side occurred. Given that random numbers will be used, you should be able to see that the higher the number of throws, the closer the results will be towards approximately equal occurrence of all sides (same probability). The program should deal gracefully with incorrect type of arguments through checks and exceptions.
This program can be in fact an extension of the coin thrower program which can be found on the Week 2 Random Number Generation lecture material. You may implement it in a similar manner to the coin thrower program, i.e. if any user input is incorrect you could print out a diagnostic message and terminate the program. But the most sophisticated implementation is one in which you keep asking the user for a correct value when her input is wrong. In this case, you could use separate functions getNFaces() and getNThrows(nfaces) which use a loop to get the value correctly – see for example the getNDataFromKeyboard() static method of assignment part 1B.
You should start working on this assignment in the first lab session of the week commencing 15 January.
1st PROGRAMMING ASSIGNMENT – Part 1B
Calculating the Mean and Variance of a Data Set – “the Long Way”
This is another introductory programming exercise so that you start getting familiar with some more sophisticated aspects of Python. “The long way” is mentioned above because the description of this assignment also serves as a tutorial introduction to various aspects of structured and object-oriented programming in Python, and for this reason this description is 5 pages long. It also includes a good part of the assignment already implemented in order to show how things should be done properly. So please go through this description very carefully as it constitutes effectively an additional complementary lecture.
The program to be developed in this exercise should calculate the mean and variance of a set of numbers, i.e. “the data set”. This is something that could be easily done in C through a program that would have the following structure: two C functions mean and variance and a main program that initialises an array of numbers, invokes the two functions bypassing to them the array as parameter and prints the respective results. The “signature” of the two functions would be the following:
float mean (int ndata, float data[])
float variance (int ndata, float data[])
Note that in C we need to pass the size of the array, i.e. ndata, as a separate parameter, as the array is effectively only a pointer to its first element, no more than that.
We could write a similar program in Python by mirroring exactly the structure of the C program, but given that this year you will learn about object-oriented (O-O) programming, we will do it slightly differently. We will create a reusable class for the data set which will include various functions (or, more precisely, methodsin O-O terminology) for initialising the data in a number of ways: by getting it from the keyboard, by generating random values in a particular specified range or by reading the data values from a file. After the assignment, this class could be put aside and be possibly used in other contexts.
We will also write the mean and variance functions, which in Python will have the following simpler signature:
def mean (data)
def variance (data)
Finally, we will write a main program which will allow the initialisation of the data set in a number of ways and will then compute the mean and standard deviation.
We are now ready to implement our first simple object-oriented class and program in Python in an incremental manner, showing basic parts of it and its overall layout but omitting the complete implementation, which you should do.
import random # for Random class methods in the full version
class NumberList:
def__init__ (self): # the class constructor
self.__data = [] # initialises the __data “private” instance variable to an empty list
def getData (self):
return self.__data; # returns the contained data list to users of the class
def setData (self, data): # initialises the list with “externally-created” data
self.__data = data
# end class
def mean (data):
# function implementation goes here, you should do this
def variance (data):
# function implementation goes here, you should do this
def main ():
mydata = [0.1, 1.1, 2.1, 3.1, 4.1] # hardcoded data set values, list with 5 elements
nlist = NumberList() # create new empty NumberList object instance
nlist.setData(mydata) # fill it in with the data set
print("Numbers: " + str(nlist.getData())) # print the data set
print("Mean: " + str(mean(nlist.getData()))) # calculate and print mean
print("Variance: " + str(variance(nlist.getData()))) # calculate and print variance
if__name__ == "__main__":
main()
Note: in the main function above we could have passed directly mydata to the mean & variance functions. But we did it in an object-oriented manner by creating a NumberList object instance which contains mydata and then retrieved the contained data using the getData() method in order to to pass it to the mathematical functions. In a more complex program, such a data set object could have been created and filled in elsewhere and passed as parameter to a function in order to calculate the data set mean & variance, so we used this more general approach.
We have now implemented our first Python program which calculates the mean and variance of a data set with “hard-coded” values, with the data set implemented in an object-oriented manner through the NumberList class. It would be nice to extend this class to be able to get the data set size and values in various ways: by a human user from the keyboard, by randomly producing the values within a particular range, or by reading a file which contains the data values, one per line.
Considering the data-from-keyboard approach, we introduce the getNDataFromKeyboard() method which will read the number of data elements expected from the keyboard. It will also need to check that the number specified by the user is >= 2 as otherwise there is no point in running the program. This method should be private, given that it will be only called by another class method getDataFromKeyboard() which we will subsequently introduce. Hence we name the former __ getNDataFromKeyboard() according to the Python convention for naming private class members. We include the complete method implementation overleaf.
# additional NumberList class methods
def__getNDataFromKeyboard (self): # “private” method names in Python start with __ print("Enter the number of data set elements: ")
ndata = 0
gotNDataCorrectly = False # a flag to loop until we get ndata correctly
while gotNDataCorrectly == False:
try:
ndata = float(input()) # read from the keyboard, accept also strings & convert
if ndata % 1 == 0 and ndata >= 2: # check for integer input >= 2
gotNDataCorrectly = True
else:
print("__getNDataFromKeyboard: ndata should be >=2")
except (ValueError, SyntaxError):
print("__getNDataFromKeyboard: ndata should be an integer!")
# end while loop
return int(ndata) # return ndata as int
def getDataFromKeyboard (self):
ndata = self.__getNDataFromKeyboard()
# here you should write code that gets exactly ndata numbers from the keyboard # and adds them to the __data instance variable using the list append method;
# you will need a while loop in similar fashion to __getNDataFromKeyboard
Note that the getNDataFromKeyboard method does not use the __data instance variable. It could be made in fact a static class method, static methods are those that do not have access to the class instance variables and, in fact, can be called without creating an object instance by simply preceding them with the class name, e.g. NumberList. getNDataFromKeyboard(). In order to make this method static, we need to use the @staticmethod decorator and in this case the method would not take the self parameter while everything else would stay the same. Although it does not make any difference when running the program, it is better programming practice and you should do it that way.
@staticmethod # this decorator tells the interpreter that the following method is static
def__getNDataFromKeyboard (): # note the absence of self, static methods do not have it # normal method implementation follows
Let’s now introduce the getRandomData(ndata, range1, range2) method which will produce a random data set in [range1..range2). In Python, random numbers in [0..1) are produced by the random() method of the Random class which is accessible through the “hidden” random object reference - hidden means that it exists in the background without having to create it explicitly, i.e. random = Random(). See also lecture 2 on Random Number Generation.
By implementing this method, we will also get to learn another Python feature, that of optional parameters. By assigning the “default value” 0 to range2, it means that the range2 parameter maybe omitted by calling the method using getRandomData(ndata, range1) and its value will be 0; the method will then produce values in [0..range1). If on the other hand the range2 parameter is included by using getRandomData(ndata, range1, range2), then the method should produce values in [range1..range2); note it should be range1 < range2, otherwise the method should print out an error message and do nothing. Also note that the parameters ndata, range1 and range2 could be either integers or stringified integers, e.g. 10 or “10”, and the method code should cater for both cases.
def getRandomData (self, ndata, range1, range2=0):
# here you should write code that first checks the validity of the parameters
# then sets two variables low and high according to the range1 and range2 values # and finally produces random values and adds them to __data using list append
Finally, we can also add a final method to our NumberList class to initialise the data set by reading values from a file. By doing this, you will learn some elementary file manipulation, although more elaborate file handling will be taught in the second part of the term. You should use the open function to open the file in read mode and then in a for loop you should go through every line of the file, using the strip method of every text line by doing strip(‘\n’) to remove any spaces and the newline character and convert the resulting value to float, making sure that you catch exceptions if the value cannot be converted. The signature of the method will be:
def getDataFromFile (self, fileName):
# method implementation follows
Having introduced all these methods, we have now created a useful class NumberList. It includes the methods getDataFromKeyboard, getRandomData and getDataFromFile which can be easily reused in different contexts, saving development time.
We can now rewrite our main program to use the getDatatFromKeyboard method and make it more flexible than using a fixed size list with hard-coded values, which we did before:
def main ():
nlist = NumberList()
nlist.getDataFromKeyboard()
print("Numbers: " + str(nlist.getData()))
print("Mean: " + str(mean(nlist.getData())))
print("Variance: " + str(variance(nlist.getData())))
We can also rewrite our main program to use either the getRandomDataSet or getDataFromFile methods; in the first case, we will hardwire the values for ndata and upper bound while in the second case we will hardwire the name of the data file. In order to save space, we use one main function in which as can comment in/out the right method accordingly:
def main ():
nlist = NumberList()
# this version uses getRandomData, could comment out and comment in getDataFromFile nlist.getRandomData2(5, 10) # produce 5 random values in the [0, 10) range
# nlist.getDataFromFile(“dataFile”) # read values from file with name dataFile
print("Numbers: " + str(nlist.getData()))
print("Mean: " + str(mean(nlist.getData())))
print("Variance: " + str(variance(nlist.getData())))
So we implemented the two different main programs above in only a few lines of code by using the class NumberList which we can reuse anywhere. A key aspect of object-oriented programming is to design and implement highly reusable classes and this exercise demonstrated the benefit of doing this.
But in order to also demonstrate some other aspects of Python and programming languages in general, we will create a more sophisticated version of the main program. This will combine the three options we used above; it will also allow the user to pass the size and low/high of the random data set from the command line. So when the program is invoked with no arguments at all it will get the values from the keyboard; when it is invoked with one argument this should be the name of a file and it will read the data from a file; and when it is invoked with two or three arguments, it should produce the data set values randomly.
Also as NumberList is a reusable class, we will leave it in file NumberList.py which we have used until now and we will put the more sophisticated main program described above in file MeanAndVariance.py - see implementation below.
from NumberList import NumberList # NumberList class is in file NumberList.py import sys # for sys.argv and sys.exit()
def main ():
nlist = NumberList() # create an empty NumberList instance
nargs = len(sys.argv) # argv contains the program name and arguments, as in C
if nargs == 1: # no arguments, actually only the program name hence value 1
nlist.getDataFromKeyboard()
elifnargs == 2: # filename argument, get data from file
nlist.getDataFromFile(sys.argv[1])
elifnargs == 3 or nargs == 4: # produce data set randomly
if nargs == 3:
nlist.getRandomData(sys.argv[1], sys.argv[2])
else: # nargs = 4
nlist.getRandomData(sys.argv[1], sys.argv[2], sys.argv[3])
else:
print(“incorrect number of arguments, try again”);
sys.exit() # terminate program
print("Numbers: " + str(nlist.getData()))
print("Mean: " + str(mean(nlist.getData())))
print("Variance: " + str(variance(nlist.getData())))
By studying carefully the description of this assignment and by implementing this program you will get familiar with a number of Python features and get introduced to object-oriented programming. As already stated in the beginning, the detailed description of this assignment serves as an introductory tutorial to object-oriented programming. Another aspect of this assignment is that it introduces “incremental development”: you first implement a simple program that works with a fixed size / hard-coded values data set, then extend it to work with a data set that the user provides from the keyboard, then extend it to also work by producing the data set randomly with a user-specified size and range; then extend it to also work by reading the data set values from a file; and finally enhance the main function to enable running the program with all these options.
1st PROGRAMMING ASSIGNMENT – Part 1C
Shape Inheritance
This exercise has the purpose first to get you to implement the Shape, Point, Circle and Cylinder classes as in the lecture notes in order to get to understand better, assimilate and actually code the inheritance features taught in the lectures. Although you can simply copy the code from the notes, it would be certainly more beneficial to write the code yourselves by looking at the notes in order to realise how object-oriented features related to inheritance are exercised and understand / assimilate the relevant principles. In addition to the classes in the notes, you should also design and implement the following shape classes exploiting inheritance: Sphere, Rectangle, Square and Cube.
Having implemented these classes, you should write a program which gets input from the user/keyboard to create an instance of any one of these. The user should be able to create as many of these shapes and s/he wants. The menu should also allow the user to print out the created objects, either selecting a particular one or printing all of them. The user should also be allowed to remove/delete an existing shape from the list. Finally, the user should be allowed to modify a particular shape. The program should print the objects it keeps by using only the Shape getName(), toString(), getArea() and getVolume() methods, i.e. treating all these objects “polymorphically” as “shapes”. Note that modifying a shape cannot be done polymorphically, specific functions will be required to modify each type of shape. The program should deal gracefully with incorrect type of arguments through checks and exceptions.
ASSIGNMENT SUBMISSION AND EXAMINATION
You should also submit the following code files on Moodle by 9am on Monday 5 February:
1. VDiceThrower.py - the virtual dice thrower program
2. NumberList.py - the reusable NumberList class
3. MeanAndVariance.py - the mean and variance program
4. Shapes.py - the shape classes and the test program in one file
The file names above are indicative, you may use alternative names if you wish.
You should demonstrate the working programs to the lab TAs in a session during the week starting 5 February. You will be also asked questions about your code. Nicely structured, presented and commented code is very important and will affect the overall mark.