简体   繁体   English

Python中的面向对象编程

[英]Object Oriented programming in Python

I am defining a class called 'car' I am comparing it to a document that runs a series of tests on my class. 我正在定义一个名为“汽车”的类,并将其与对我的类进行一系列测试的文档进行比较。 However, I am getting errors, and I am not sure why. 但是,我遇到了错误,并且不确定为什么。 Here's my code. 这是我的代码。 The Drive method is supposed to take the car and move it a specified amount of miles. 应采用Drive方法将汽车移至指定的距离。 If the car can achieve all the miles with the given amount of fuel, then the car makes the trip and outputs the miles. 如果汽车可以在给定的燃油量下达到所有里程,则汽车进行行驶并输出里程。 If it can't, it goes the maximum amount of miles it can. 如果不能,它将达到最大里程数。 The addFuel method is supposed to add fuel to the car, but if it overflows it doesn't add any fuel, and if the parameter specified isn't an integer, or isn't a positive value, it's supposed to throw an exception. addFuel方法应该为汽车添加燃料,但是如果它溢出,则不会添加任何燃料,并且如果指定的参数不是整数或不是正值,则应该引发异常。 And the tripRange module is supposed to be given the amount of gallons in the car, and determine how many miles you will travel. 并且应该给tripRange模块提供汽车中的加仑量,并确定您将行驶多少英里。 Below I have posted my code first, and then the code to test it out. 在下面,我先发布了我的代码,然后发布了代码进行测试。 Can you help me? 你能帮助我吗? I appreciate it. 我很感激。

#Define the class


class Car(object):

    def __init__(self,fuelEfficiency=0,fuelCapacity=0,fuelLevel=0,odometer=0):
        self.setCar(fuelEfficiency,fuelCapacity,fuelLevel,odometer)

    def setFuelEfficiency(self,newFuelEfficiency):
        self.setCar(fuelEfficiency = newFuelEfficiency)

    def setFuelCapacity(self,newFuelCapacity):
        self.setCar(fuelCapactity = newFuelCapacity)

    def setFuelLevel(self,newFuelLevel):
        self.setCar(fuelLevel = newFuelLevel)

    def setOdometer(self,newOdometer):
        self.setCar(odometer = newOdometer)

    def setCar(self,fuelEfficiency = None,fuelCapacity = None,fuelLevel = None,odometer = None):
        if fuelEfficiency == None:
            fuelEfficiency = self.getFuelEfficiency

        if fuelCapacity == None:
            fuelCapacity = self.getFuelCapacity

        if fuelLevel == None:
            fuelLevel = self.getFuelLevel

        if odometer == None:
            odometer = self.getOdometer

        self.fuelEfficiency = fuelEfficiency
        self.fuelCapacity = fuelCapacity
        self.fuelLevel = fuelLevel
        self.odometer = odometer

    def drive(self,miles):
        if miles < 0:
            return ("The car is not driven")

        milesDriven = miles/self.fuelEfficiency

        if milesDriven < self.fuelLevel:
            print("The car drove {} miles".format(miles))
        else:
            if self.fuelLevel == 0:
                print("The car drove 0 miles")
            else:
                newMiles = milesDriven * miles
                print("The car drove {} miles".format(newMiles))

        self.fuelLevel = self.fuelLevel - milesDriven
        self.odometer += miles

    def getCar(self):
        #Returns a tuple that has (FE,FC,FL,OD)
        return (self.fuelEfficiency,self.fuelCapacity,self.fuelLevel,self.odometer)        


    def addFuel(self,num):
        if type(num) == str:
            raise KeyError("String valued enter, an integer was expected.")
        if num < 0:
            print("Sorry, you need to enter a postive number.")
        if num + self.fuelLevel > self.fuelCapacity:
            return self.fuelLevel
        else:
            return self.fuelLevel + num

    def getFuelEfficiency(self):
        return self.getCar()[0]

    def getFuelCapacity(self):
        return self.getCar()[1]

    def getFuelLevel(self):
        return self.getCar()[2]

    def getOdometer(self):
        return self.getCar()[3]

    def tripRange(self):
        numOfMiles = self.fuelEfficiency 
        return numOfMiles

    def __str__(self):
        FE = self.getFuelEfficiency()
        FC = self.getFuelCapacity()
        FL = self.getFuelLevel()
        OD = self.getOdometer()

        string = '{}:{}:{}:{}'.format(FE,FC,FL,OD)
        return string

And here's the test code: 这是测试代码:

from car import *

def checkCar(car, expected, message):
    global errorsFound
    mpg, cap, level, odo = expected
    if car.getFuelEfficiency() != mpg:
        errorsFound = True
        print(message + ': Error efficiency. Expected ' + str(mpg))
        print('\tCar:', car)
    if car.getFuelCapacity() != cap:
        errorsFound = True
        print(message + ': Error capacity. Expected ' + str(cap))
        print('\tCar:', car)
    if car.getFuelLevel() != level:
        errorsFound = True
        print(message + ': Error level. Expected ' + str(level))
        print('\tCar:', car)
    if car.getOdometer() != odo:
        errorsFound = True
        print(message + ': Error odometer. Expected ' + str(odo))
        print('\tCar:', car)

def checkNum(value, expected, message):
    global errorsFound
    if value != expected:
        errorsFound = True
        print(message + ': Error value. Expected {}. Got {}'.format(expected, value))

def main():
    c = Car(25, 15)
    checkNum(c.tripRange(), 0, 'Test 1')    

    expected = (25, 15, 0, 0)
    checkCar(c, expected, 'Test 2')

    c.addFuel(-1)
    checkCar(c, expected, 'Test 3')

    c.addFuel(1000)
    checkCar(c, expected, 'Test 4')

    c.addFuel('doctor')
    checkCar(c, expected, 'Test 5')

    c.addFuel(0)
    checkCar(c, expected, 'Test 6')

    c.addFuel(15)
    expected = (25, 15, 15, 0)
    checkCar(c, expected, 'Test 7')

    c.drive(50)
    expected = (25, 15, 13, 50)
    checkCar(c, expected, 'Test 8')

    c.drive(100000)
    expected = (25, 15, 0, 375)
    checkCar(c, expected, 'Test 9')

    c.drive(5)
    expected = (25, 15, 0, 375)
    checkCar(c, expected, 'Test 10')

    c.addFuel(10)
    expected = (25, 15, 10, 375)
    checkCar(c, expected, 'Test 11')

    c.drive(-1)
    expected = (25, 15, 10, 375)
    checkCar(c, expected, 'Test 12')

    c.drive(0)
    expected = (25, 15, 10, 375)
    checkCar(c, expected, 'Test 13')

    checkNum(c.tripRange(), 250, 'Test 14')

    if not errorsFound:
        print('No Errors Found')



errorsFound = False
main()

Your code works as expected. 您的代码按预期工作。 Altough I found a number of indentation errors in the car.py file So that may be why. 虽然如此,我在car.py文件中发现了许多缩进错误,所以这可能就是原因。 specifically the __init__ method for the Car object you have def__init__(..) , theres no space. 特别是您拥有def__init__(..)Car对象的__init__方法,没有空间。

If your talking about the exception that get thrown at you in the terminal output: 如果您在终端输出中谈论抛出的异常:

Test 1: Error value. Expected 0. Got 25
Sorry, you need to enter a postive number.
Traceback (most recent call last):
  File "/home/crispycret/Desktop/testcase.py", line 89, in <module>
    main()
  File "/home/crispycret/Desktop/testcase.py", line 42, in main
    c.addFuel('doctor')
  File "/home/crispycret/Desktop/car.py", line 64, in addFuel
    raise KeyError("String valued enter, an integer was expected.")
KeyError: 'String valued enter, an integer was expected.'
[Finished in 0.1s with exit code 1]

That's to be expected. 这是意料之中的。 As for the reason in the main() function in your test.py on line 42, your trying to do c.addFuel('doctor') , where inside the Car.addFuel() method you raise KeyError("String valued enter, an integer was expected.") when the type of input is a string. 至于第42行test.py main()函数中的原因,您尝试执行c.addFuel('doctor') ,在Car.addFuel()方法内部,您引发Car.addFuel() KeyError("String valued enter, an integer was expected.")如果输入的类型是字符串,则应为KeyError("String valued enter, an integer was expected.")

By the way you should use proper exceptions when raising errors, in this case you should use a TypeError("String valued enter, an integer was expected.") to express that the variable type was wrong. 顺便说一下,在引发错误时应使用适当的异常,在这种情况下,应使用TypeError("String valued enter, an integer was expected.")表示变量类型错误。

https://docs.python.org/2/tutorial/errors.html https://docs.python.org/2/tutorial/errors.html

Python is not Java, so don't write like it is. Python不是Java,所以不要这样写。

Getters and Setters are often not needed, so don't add them, you can always do it easily later if needed. 通常不需要使用Getter和Setter,因此不要添加它们,如果需要的话,以后随时可以轻松进行。 There is no enforced instance member protection either, but the underscore in self._odometer signals to the reader that _odometer is private. 也没有强制的实例成员保护,但是self._odometer中的下划线向读者表明_odometer是私有的。

Abandon type declaration and embrace duck-typing. 放弃类型声明并接受鸭子输入。 In addFuel() you check to see if the argument is of type str and proceed if it isn't. addFuel()您检查参数是否为str类型,如果不是,则继续。 However, the argument could be of type file, module, dict, list, and so on. 但是,参数可以是文件,模块,字典,列表等类型。 You can't check them all, so it is best not to try. 您无法全部检查所有内容,因此最好不要尝试。

Of what remains, drive() is broken, but now obviously so because so much junk has been removed and tripRange() was redundant. 剩下的东西, drive()坏了,但是现在很明显是因为删除了那么多垃圾,并且tripRange()是多余的。 This leaves one working method addFuel and it is hard to make the case for testing two simple lines of code. 这样就留下了一个工作方法addFuel ,很难为测试两行简单的代码提供理由。

class Car(object):
    def __init__(self, efficiency=0, capacity=0, fuel=0, odometer=0):
        self.efficiency = efficiency
        self.capacity = capacity
        self.fuel = fuel
        self.odometer = odometer

    # four useless setters removed

def drive(self, miles):
    # argument test removed

    # miles / (miles / 1 gallon) = miles * (1 gallon / miles) = 1 gallon
    # so this expression and thus method are broken
    one_gallon = miles / self.efficiency

    if one_gallon < self.fuel:
        print("The car drove {} miles".format(miles))
    elif self.fuel == 0:
            print("The car drove 0 miles")
    else:
       newMiles = milesDriven * miles
       print("The car drove {} miles".format(newMiles))

    self.fuel -= one_gallon
    self.odometer += miles      

def addFuel(self, volume):
    # Even more argument tests removed.
    if volume + self.fuel <= self.capacity:
        self.fuel += volume

# The method "tripRange()" is equivalent to "car.efficiency" so is removed

def __str__(self):
    # trivial getters don't exist; the format template is now conventional
    return '<Car {}, {}, {}, {}>'.format(self.efficiency, self.capacity,
        self.fuel, self.odometer)

You are getting errors in your tests probably because 2/3 of your methods were broken, not even considering the peculiar getCar() and all the trivial setters and getters. 您可能在测试中出现错误,可能是因为您的方法有2/3被破坏了,甚至没有考虑到特殊的getCar()以及所有琐碎的setter和getter。 You need to write much less code than you have. 您需要编写的代码比以前少得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM