首页 > 解决方案 > Python:无和尝试除外

问题描述

我正在为预算计划制作测试工具。个人购买由 Item 类表示。如果类初始化不正确,我想返回 None。但是,当我运行我的测试工具时,它不会将变量检测为无。为什么测试工具没有将项目检测为无?

def __init__(self, nameItem, costItem):

    try: 

        if costItem < 0.00 or type(nameItem) is not str:
            self = None
        else:

            if len(nameItem) < 1:
                self = None
            else:
                self.name = nameItem
                self.cost = round(costItem,2)

                if self.name == None or self.cost == None:
                    self = None
    except:
        self = None
#Test Case

currentTest = currentTest + 1
    print("Test" ,currentTest,":Create invalid item using negative cost.")
    try:
        testItem = Item("Coffee",-1.00)
        if testItem is None:
            print("Made None value when given incorrect data:TEST PASSED")
            passTests = passTests + 1
        else:
            raise TypeError
    except TypeError:
        print("Error when creating item, created item instead of detecing error:TEST FAILED")
        failedTests.insert(failedCount,currentTest)
        failedCount = failedCount + 1
    except:
        print("Error when conducting test:TEST FAILED")
        failedTests.insert(failedCount,currentTest)
        failedCount = failedCount + 1

标签: pythonunit-testingtestingtry-catch

解决方案


内部__init__()(或任何类方法)self是一个局部变量,绑定到调用此方法的对象。分配给它只会影响该局部变量的绑定,它不会更改对存在于方法之外的对象的实际引用。

当你到达时__init__,对象已经被分配了——你也许可以用一些“诡计”来扭转它,但我不确定这是否是一个好主意,即使可能

处理初始化问题的正常 (a)方法是简单地抛出一个异常,该异常可以被捕获以适当地重新绑定变量(或根据需要执行其他操作):

try:
    item = className()
except:
    item = None

您甚至可以提供一个辅助函数来为您完成繁重的工作,因此构建仍然只需要一行,例如:

class ClassName:
    def __init__(self, makeFail):
        if makeFail: raise Exception("ouch")

def tryMake(cls, *args):
    try:
        return cls(*args)
    except:
        return None

print(tryMake(ClassName, False)) # equiv: print(ClassName(False))
print(tryMake(ClassName, True))

从输出中可以看出,它将失败的构造转换为None

<__main__.ClassName object at 0x7f7ed1e38c70>
None

但是,如果您真的想执行您建议的操作但不想捕获异常或通过辅助函数重新绑定,则存在另一种可能性。

之前调用了另一个魔术函数,它能够返回不同类型。只有当它返回请求的类型时,Python 才会调用它。__new____init____init__

因此,您可以定义__new__调用来检查价格并在类型无效时拒绝实例化类型,如下面的示例代码所示:

class Item:
    def __new__(cls, item, price):
        if price < 0:
            return None
        return super(Item, cls).__new__(cls)

    def __init__(self, item, price):
        self.item = item
        self.price = price

    def __str__(self):
        return f"({self.item}, {self.price})"

print(Item("Coffee", 4.50))
print(Item("Tea", -1))
print(Item("Biscuit", 2.75))

这似乎是你想要的输出:

(Coffee, 4.5)
None
(Biscuit, 2.75)

现在这可能不是会做的事情,而是宁愿抛出异常__init__()并让调用者以他们选择的任何方式处理它(如果需要,包括使用辅助函数)。


(a)定义为:

正常 (n) - 不会让经验丰富的 Python 开发人员质疑您的理智 :-)


推荐阅读