6

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.

user3827426
  • 103
  • 1
  • 5
  • 5
    Why do you want to do that instead of raising an exception? – BrenBarn Aug 18 '14 at 00:18
  • 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. – user3827426 Aug 18 '14 at 03:19

6 Answers6

7

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.

Devin
  • 2,113
  • 2
  • 22
  • 28
4

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.

hrunting
  • 3,857
  • 25
  • 23
1

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...
Community
  • 1
  • 1
Luzanne
  • 138
  • 6
1

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)
abhimanyu
  • 730
  • 1
  • 10
  • 23
0

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.

thiruvenkadam
  • 4,170
  • 4
  • 27
  • 26
-4

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
TulkinRB
  • 590
  • 1
  • 6
  • 10
  • But returning `None` from within an `__init__` still allows the construction to go forward. While it’s true that this is a valid way to check that arguments are certain types inside a function or method (though I’m not sure it’s wise to be checking *types* when you could be checking *supported behavior*), it’s not useful inside `__init__`. – icktoofay Aug 18 '14 at 00:27