user3827426
user3827426

Reputation: 103

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.

Upvotes: 6

Views: 6670

Answers (6)

abhimanyu
abhimanyu

Reputation: 894

If the parameters are present create class instance else None Object

class Test:

    def __init__(self, *args, **kwargs):
        pass

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

Upvotes: 1

Devin
Devin

Reputation: 2133

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.

Upvotes: 7

thiruvenkadam
thiruvenkadam

Reputation: 4260

In the init, in case of exception just put a return. That will do the trick.

class MyTest(object):
    def __init__(self, * args, **kwargs):
        try:
            # Your code goes here
        except:
            print "No donuts buddy"
            return
            # An  empty return will return a None

In case you wish to instantiate another class or any such advanced maneuvers, you need to write a __ new __ constructor in your class instead of doing it in the __ init __ constructor.

Upvotes: 0

Luzanne
Luzanne

Reputation: 138

If you want to set the object to None, I assume that in other places of your code, you are going to test for the object being None (before assuming it's a genuine Node). So maybe, a custom __nonzero__ method could do the trick (see this question), eg:

class MyNode():
  def __init__(self, ...):
    self.ok = False
    if ...genuine node...:
      self.ok = True
      ...
  def __nonzero__(self):
    return self.ok


node = MyNode(...)
if node:
  ...node code...
else:
  ...leaf code...

Upvotes: 1

TulkinRB
TulkinRB

Reputation: 610

you can use the isinstance(object, class) function inside an if statment to check each parameter for example:

if not isinstance(num, int):
    return None

Upvotes: -4

hrunting
hrunting

Reputation: 3947

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.

Upvotes: 4

Related Questions