Python: нет и попробуйте, кроме - PullRequest
0 голосов
/ 04 августа 2020

Делаю тестовую шлейку для бюджетной программы. Отдельные покупки представлены классом Item. Если класс инициализирован неправильно, я хочу вернуть None. Однако, когда я запускаю свою тестовую программу, она не определяет, что переменная имеет значение None. Почему тестовая оснастка не определяет элемент как 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

Ответы [ 3 ]

1 голос
/ 04 августа 2020

Внутри __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

Однако существует другая возможность, если вы действительно хотите сделать что-то вроде того, что вы предлагаете, но не хотите перехватывать исключения или повторно связываться с помощью вспомогательной функции.

Есть другая magi c функция __new__, которая вызывается до __init__ и которая является способной возвращать другой тип. Только если он вернет запрошенный тип, будет Python, а затем __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)

Теперь это, вероятно, не то, что I сделал бы , вместо этого предпочитая генерировать исключение в __init__() и позволить вызывающей стороне позаботиться об этом любым способом, который они выберут (включая использование вспомогательной функции, если это необходимо).

(a) Определено как:

normal (n) - таким образом, чтобы не вызывать Python разработчиков, чтобы поставить под сомнение вашу вменяемость: -)

0 голосов
/ 04 августа 2020

В вашей функции __init__ есть концептуальная ошибка: устанавливая self на None , вы создаете новую метку с именем self с None значение, вы не устанавливаете исходный объект на None .

Когда вызывается __init__, это означает, что объект только что был создан.

Если вы хотите запретить создание объекта, вы должны использовать __new__, но вы должны использовать исключение , невозможно обнулить значение объекта.

0 голосов
/ 04 августа 2020

Может иметь какое-то отношение к вашему значению -1.00, попробуйте назначить его как float внутри функции или init. Например:

def init (self, nameItem, float (costItem)):

Если costItem

testItem = Item ( «Кофе», поплавок (-1.00))

...