Class instantiation question

T

Todd Johnson

Ok, say I have a class MyClass and an __init__(self,
a, b) Say that a and b are required to be integers
for example. So my init looks like:

__init__(self, a, b):
try:
self.one = int(a)
self.two = int(b)
except ValueError:
#nice error message here
return None

I have even tried a similar example with if-else
instead of try-except, but no matter what if I call

thisInstance = MyClass(3, "somestring")

it will set self.one to 3 and self.two will be
uninitialised. The behavior I am hoping for, is that
thisInstance is not created instead(or is None). How
do I get the behavior I am looking for?

Thanks in advance,
Todd

__________________________________
Do you Yahoo!?
The New Yahoo! Shopping - with improved product search
http://shopping.yahoo.com
 
A

anton muhin

Todd said:
Ok, say I have a class MyClass and an __init__(self,
a, b) Say that a and b are required to be integers
for example. So my init looks like:

__init__(self, a, b):
try:
self.one = int(a)
self.two = int(b)
except ValueError:
#nice error message here
return None

I have even tried a similar example with if-else
instead of try-except, but no matter what if I call

thisInstance = MyClass(3, "somestring")

it will set self.one to 3 and self.two will be
uninitialised. The behavior I am hoping for, is that
thisInstance is not created instead(or is None). How
do I get the behavior I am looking for?

Thanks in advance,
Todd

If I'm correct, __init__ method is somewhat different from what you
expect: it *doesn't* return values (None is just a fake return value).
Actually MyClass(...) proceeds more or less in the following way:

1) create an object
2) call __init__ with parameters passed
3) return the object's reference.

Therefore, you cannot prevent object creation in __init__. You can only
throw an exception.

Actually, I see no reason to use if/then instead try/except or maybe
even simple self.one = int(a) (that will throw if anythins goes wrong),
but if you want, for example, to create another object depending on
parameters passed, take a look at __new__ method.

regards,
anton.
 
C

Carl Banks

Todd said:
Ok, say I have a class MyClass and an __init__(self,
a, b) Say that a and b are required to be integers
for example. So my init looks like:

__init__(self, a, b):
try:
self.one = int(a)
self.two = int(b)
except ValueError:
#nice error message here
return None

I have even tried a similar example with if-else
instead of try-except, but no matter what if I call

thisInstance = MyClass(3, "somestring")

it will set self.one to 3 and self.two will be
uninitialised. The behavior I am hoping for, is that
thisInstance is not created instead(or is None). How
do I get the behavior I am looking for?


1. I highly recommend you rethink your programming. Are you planning
to handle the error in the function that called the MyClass
contructor? In other words, are you doing something like this:

def some_function(a,b):
thisInstance = MyClass(a,b)
if thisInstance is None:
handle_error()
else:
do_something_useful(thisInstance)

If so, you are not taking full advantage of the exception handling
mechanism. The best way to do it is like this:

def some_function(a,b):
try:
thisInstance = MyClass(a,b)
except ValueError:
handler_error()
else:
do_something_useful(thisInstance)

As always, a larger code snippet can help us help you with that, if
you wish.


2. If you're sure the behavior you want is to return None if a or b is
not an integer, then I recommned you use a factory function:

def my_class_maker(a,b):
try:
return MyClass(a,b)
except ValueError:
return None


--
CARL BANKS http://www.aerojockey.com/software

As the newest Lady Turnpot descended into the kitchen wrapped only in
her celery-green dressing gown, her creamy bosom rising and falling
like a temperamental souffle, her tart mouth pursed in distaste, the
sous-chef whispered to the scullery boy, "I don't know what to make of
her."
--Laurel Fortuner, Montendre, France
1992 Bulwer-Lytton Fiction Contest Winner
 
D

David C. Fox

Todd said:
Ok, say I have a class MyClass and an __init__(self,
a, b) Say that a and b are required to be integers
for example. So my init looks like:

__init__(self, a, b):
try:
self.one = int(a)
self.two = int(b)
except ValueError:
#nice error message here
return None

I have even tried a similar example with if-else
instead of try-except, but no matter what if I call

thisInstance = MyClass(3, "somestring")

it will set self.one to 3 and self.two will be
uninitialised. The behavior I am hoping for, is that
thisInstance is not created instead(or is None). How
do I get the behavior I am looking for?

As far as I know, the only way to prevent __init__ from creating an
instance is for __init__ to raise an exception which is NOT caught and
handled within __init__. In your example, I think simply doing

class MyClass(self, a, b):
def __init__(self, a, b):
self.one = int(a)
self.two = int(b)

without the try...except block should do it. Then the calling code can
handle the ValueError appropriately.

David
 
M

Matt Brubeck

Todd Johnson said:
Ok, say I have a class MyClass and an __init__(self,
a, b) Say that a and b are required to be integers
for example. So my init looks like:

__init__(self, a, b):
try:
self.one = int(a)
self.two = int(b)
except ValueError:
#nice error message here
return None

I have even tried a similar example with if-else
instead of try-except, but no matter what if I call

thisInstance = MyClass(3, "somestring")

it will set self.one to 3 and self.two will be
uninitialised. The behavior I am hoping for, is that
thisInstance is not created instead(or is None). How
do I get the behavior I am looking for?

Here's one option:
.... def __init__(self, a):
.... self.a = int(a)
....Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 3, in __init__
ValueError: invalid literal for int(): hello

This also allows the following:
.... except ValueError: c = None
....None

If you really want initialization to return None instead of raising an
exception, you can override the __new__ method of a new-style class:
.... def __new__(cls, a):
.... try: a = int(a)
.... except ValueError: return None
.... return object.__new__(cls, a)
.... def __init__(self, a):
.... self.a = a
....None
 
A

Alex Martelli

Todd said:
Ok, say I have a class MyClass and an __init__(self,
a, b) Say that a and b are required to be integers
for example. So my init looks like:

__init__(self, a, b):
try:
self.one = int(a)
self.two = int(b)
except ValueError:
#nice error message here
return None

Any return statement in __init__ MUST return None (you
get an error otherwise). The job of __init__ is
preparing the self, which is already created.
I have even tried a similar example with if-else
instead of try-except, but no matter what if I call

thisInstance = MyClass(3, "somestring")

it will set self.one to 3 and self.two will be
uninitialised. The behavior I am hoping for, is that
thisInstance is not created instead(or is None). How
do I get the behavior I am looking for?

It's not a nice architecture AT ALL, but if you
insist you can have it -- as long at least as
class MyClass is new-style, e.g., subclasses
object -- by defining a __new__ method. The
process of calling a class can be summarized as:

[[ function equivalent to calling theclass with
positional args *a and named args **k ...: ]]

result = theclass.__new__(theclass, *a, **k)
if isinstance(result, theclass):
theclass.__init__(result, *a, **k)
return result

Normally, it's best to do all the work in __init__
and thus to inherit __new__ from type object.
But that's only for the NORMAL case, where one
assumes that calling theclass always either
raises / propagates an exception OR else returns
an instance of theclass. Since you deliberately
want to break this normal, expected rule --
having the call to theclass return None instead! --
you would need to define __new__.

For example:


class theclass(object):

def __new__(cls, a, b):
self = object.__new__(cls)
try:
self.one = int(a)
self.two = int(b)
except ValueError:
#nice error message here
return None
else:
return self

I would still recommend you to reconsider the
architecture you want. Why MUST you break all
normal Pythonic expectations of users of your
class...? If you must, Python lets you -- but
MUST you, really...?


Alex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top