171

I have a class with an __init__ function.

How can I return an integer value from this function when an object is created?

I wrote a program, where __init__ does command line parsing and I need to have some value set. Is it OK set it in global variable and use it in other member functions? If so how to do that? So far, I declared a variable outside class. and setting it one function doesn't reflect in other function ??

4
  • 10
    If you were considering returning an error code, raise an exception instead. Commented Mar 22, 2010 at 11:48
  • 2
    Please remove your comment and update your question. You own the question. It's your question. Please fix the question to correctly show what your real problem is. You're misusing __init__; we can help you if you describe what you're really trying to accomplish. Commented Mar 22, 2010 at 14:47
  • 3
    __init__ probably should not be doing command-line parsing. Define a class method that does the actual parsing, and pass the parsed values to __init__. Let __init__ worry about creating the necessary attributes, not figuring out how to produce the values for those attributes. Commented Jul 13, 2021 at 20:45
  • 1
    Note for future readers: If you want to get generic information back as a result of calling __init__, see the answers given here. If you want to signal that something went wrong, raise an exception. That doesn't answer the question that was asked here, but might be what you have in mind. Commented Jul 2, 2022 at 2:47

14 Answers 14

218

If you want to return some other object when a class is called, then use the __new__() method:

class MyClass:
    def __init__(self):
        print("never called in this case")

    def __new__(cls):
        return 42

obj = MyClass()
print(obj)
# Output: 42
Sign up to request clarification or add additional context in comments.

5 Comments

Yeah, new is the right way of returning something other than a class instance when using a class... I'm just wondering - is there any reason you might actually want to DO that?
@weronika One idea: in any situation where you'd normally use a factory, but you have some reason to want to present an interface that looks like normal class instantiation. Example: when adding some new optional parameters into your class's __init__, you realise that really, to provide the flexibility you want, you need a class factory that returns instances of specialised subclasses. But your library's users are already using your existing API. To preserve it, you override __new__ to return instances of your specialised subclasses.
If you want to see an example of what Mark Amery said, check out the source code of the datetime module from the Standard Library. It uses __new__ in exactly this fashion.
Also if anyone wants to do this make sure to inherit from object otherwise it won't work.
I kind of think at this pount, just using a regular function makes more sense. Might be a bit alien to folks from the Java dimension (functions not in classes? heresy!) but its pythonic. (Also you can assign properties to functions as in funtionName.val =.. which is kind of wild but it works)
176

__init__ is required to return None. You cannot (or at least shouldn't) return something else.

Try making whatever you want to return an instance variable (or function).

>>> class Foo:
...     def __init__(self):
...         return 42
... 
>>> foo = Foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() should return None

7 Comments

+1: You cannot return something else. It doesn't make any sense.
init doesn't return the newly created object - as seen in the TypeError, it is required to return None, right? The newly created object is returned by new, init just sets some of its attributes. But yes, as you said, changing init, or new, to return something else really makes no sense.
Where is new here? Is new implicit in Python? I assumed Python's semantics were different from Java and the other languages that do use this word.
@Shiva AFAIK, by new weronika meant __new__(self) not the general java semantic.
Just because it can't be done doesn't mean it doesn't make sense. It would, for instance, be nice to pass data from super().__init__ to the derived class without having to relay it through an instance variable.
|
47

From the documentation of __init__:

As a special constraint on constructors, no value may be returned; doing so will cause a TypeError to be raised at runtime.

As a proof, this code:

class Foo(object):
    def __init__(self):
        return 2

f = Foo()

Gives this error:

Traceback (most recent call last):
  File "test_init.py", line 5, in <module>
    f = Foo()
TypeError: __init__() should return None, not 'int'

Comments

24

Sample Usage of the matter in question can be like:

class SampleObject(object):

    def __new__(cls, item):
        if cls.IsValid(item):
            return super(SampleObject, cls).__new__(cls)
        else:
            return None

    def __init__(self, item):
        self.InitData(item) #large amount of data and very complex calculations

...

ValidObjects = []
for i in data:
    item = SampleObject(i)
    if item:             # in case the i data is valid for the sample object
        ValidObjects.append(item)

1 Comment

This will raise a NameError: self is not defined in __new__(cls, Item)
16

The __init__ method, like other methods and functions returns None by default in the absence of a return statement, so you can write it like either of these:

class Foo:
    def __init__(self):
        self.value=42

class Bar:
    def __init__(self):
        self.value=42
        return None

But, of course, adding the return None doesn't buy you anything.

I'm not sure what you are after, but you might be interested in one of these:

class Foo:
    def __init__(self):
        self.value=42
    def __str__(self):
        return str(self.value)

f=Foo()
print f.value
print f

prints:

42
42

4 Comments

ohh..Can i access member variable out the class ? Then that should solve my issue ....thanks
@lakshmipathi, Yes, instance variables like this are public.
As a oneliner to get something valuable returned after initiation of a class: f = Foo().value
@JLT Yes, you cam always do that but it still does not mean that anything is returned from __init__.
11

__init__ doesn't return anything and should always return None.

Comments

6

You can just set it to a class variable and read it from the main program:

class Foo:
    def __init__(self):
        #Do your stuff here
        self.returncode = 42
bar = Foo()
baz = bar.returncode

Comments

4

We can not return value from init. But we can return value using new.

class Car:
    def __new__(cls, speed, unit):
        return (f"{speed} with unit {unit}")


car = Car(42, "km")
print(car)

1 Comment

Yes, but you can't really return arbitrary values from __new__ and still have the class "protocol" make sense.
2

init() return none value solved perfectly

class Solve:
def __init__(self,w,d):
    self.value=w
    self.unit=d
def __str__(self):
    return str("my speed is "+str(self.value)+" "+str(self.unit))
ob=Solve(21,'kmh')
print (ob)

output: my speed is 21 kmh

Comments

0

Just wanted to add, you can return classes in __init__

@property
def failureException(self):
    class MyCustomException(AssertionError):
        def __init__(self_, *args, **kwargs):
            *** Your code here ***
            return super().__init__(*args, **kwargs)

    MyCustomException.__name__ = AssertionError.__name__
    return MyCustomException

The above method helps you implement a specific action upon an Exception in your test

1 Comment

super().__init__ is returning None, so you are returning None, which is fine, but redundant.
0

Met this case when tried to parse some string data into a recursive data structure, and had a counter to be passed through.

Python does not allow to return anything from __init__, but you may write a factory function, or a class method, or a Parser class, depending on the code structure and complexity of parsing, which will parse your data into data objects.

Global variable is not a good solution, as it may be changed somewhere else, breaking the parsing logic.

Function example:

class MyClass():
    def __init__(self, a, b, c):
        # only assignments here
        self.a = a
        self.b = b
        self.c = c
        # return None


def parse(data):
    # parsing here
    a = ...
    b = ...
    c = ...

    # status, counter, etc.
    i = ...

    # create an object
    my_obj = MyClass(a, b, c)
    
    # return both
    return my_obj, i


# get data and parse
data = ...
my_obj, i = parse(data)

Class method example:

class MyClass():
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c

    @classmethod
    def parse(cls, data):
        a = ...
        b = ...
        c = ...

        i = ...

        obj = cls(a, b, c)
        return obj, i


data = ...
my_obj, i = MyClass.parse(data)

Comments

0

Using __new__ is the best option, as mentioned in other answers.

Just to add a use case for why. The company I work for asked me to update our internal system from python 3.8 to 3.10 which runs on Flask, and with us still being on the 1.x.x version, I updated to 2.x.x, and that initially led to upgrading SQLAlchemy to version 2, but that created incompatibility issues around the use of db.engine.execute() calls that were all over the place still.

To fix this, I first tried a wrapper function to just replace the calls with the correct context-based engine calls, but that won't work for calls like:

db.engine.execute(sql).scalar()

because a function can't have a member function of it's own. So the solution was to create a class that could be called using both forms:

DBEngineClass(sql)

and

DBEngineClass(sql).scalar()

Where DBEngineClass has the __new__ member function defined to return the pure ResultProxy from the engine call, whereas there is also a scalar() and fetchall() member function that relies on the __init__ member function to execute the sql query and then set a result member variable to the ResultProxy, which can then be mutated and returned by the scalar() and fetchall() member functions.

So that way it reduces the overall time that we need to spend on refactoring, by making the process as simple as adding a new import statement into the affected python files, and then doing a simple find and replace to keep the same functionality, as well as make the system compatible with the newer version of SQLAlchemy.

Thanks for readind :-)

Comments

-3

solution here Yes, trying to return from the init method in python returns errors as it is a constructor of the class you can only assign values for the scope of the class but not return a specific value. if you want to return a value but do not wish to create a method, you can use str method

def __init__(self,a):
    self.value=a

   def __str__(self):
    return str("all my return values are possible here")`

2 Comments

__init__ is the initializer, not the constructor. __new__ is the constructor.
__str__ has nothing to do with returning a value from the instantiation process.
-4

Well, if you don't care about the object instance anymore ... you can just replace it!

class MuaHaHa():
def __init__(self, ret):
    self=ret

print MuaHaHa('foo')=='foo'

1 Comment

That just changes what is assigned to the name self inside that constructor.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.