Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Python, Return “None” instead of creating new instance if wrong parameters are given

when creating instance of a class, if wrong parameters are given. how do I NOT to create a new instance and return the reference, but instead just return a "None"

here is my application: Because it is allowed sometime. My application is to build trees from a list of integers. I want to use None in the list to represent a leaf. so I just want to return a None instead of a empty tree node.

like image 248
user3827426 Avatar asked Mar 18 '23 17:03

user3827426


2 Answers

Most of these answers aren't right. The appropriate way to do this is to validate your arguments in the class's __new__ method, and return None if validation fails or ins if validation succeeds.

Here's what you're looking for:

import pytest # for testing


class ValidatedModel:
    def __init__(self, *, name=None):
        self.name = name

    @classmethod
    def _validate(cls, *args, **kwargs):
        try:
            assert not args
            assert list(kwargs.keys()) == ['name']
            assert len(kwargs['name']) > 5 and len(kwargs['name']) < 10
        except AssertionError:
            return False
        return True

    def __new__(cls, *args, **kwargs):
        if cls._validate(*args, **kwargs):
            return super().__new__(cls)


class TestValidatedModel:
    def test_success(self):
        vm = ValidatedModel(name='william')
        assert isinstance(vm, ValidatedModel)

    def test_kwarg_fail_unexpected_kwarg(self):
        vm = ValidatedModel(name='william', gender='M')
        assert vm is None

    def test_kwarg_fail_name_length_short(self):
        vm = ValidatedModel(name='bill')
        assert vm is None

    def test_kwarg_fail_name_length_long(self):
        vm = ValidatedModel(name='william johnson')
        assert vm is None

    def test_no_name_kwarg(self):
        vm = ValidatedModel()
        assert vm is None

Obviously you can replace the _validate method with your own implementation.

like image 113
Devin Avatar answered Mar 21 '23 05:03

Devin


See this answer to Python __init__ return failure to create.

Basically, you can use __new__ to accomplish what you want, but really, the Pythonic way of doing this would be to throw an exception. Arguably, the Pythonic way would be to have a simpler __init__ method that is simply an initialization and not something that can fail at all.

like image 35
hrunting Avatar answered Mar 21 '23 05:03

hrunting