Class instantiation question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Todd Johnson

    Class instantiation question

    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
    Yahoo Shopping is your guide to the latest deals and product reviews from the stores you love. Find sales and discounts on featured brands, shop for gifts, read our buying guides and more.


  • anton muhin

    #2
    Re: Class instantiation question

    Todd Johnson wrote:
    [color=blue]
    > 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[/color]

    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.

    Comment

    • Carl Banks

      #3
      Re: Class instantiation question

      Todd Johnson wrote:[color=blue]
      > 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?[/color]


      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_us eful(thisInstan ce)

      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_us eful(thisInstan ce)

      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

      Comment

      • David C. Fox

        #4
        Re: Class instantiation question

        Todd Johnson wrote:
        [color=blue]
        > 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?[/color]

        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

        Comment

        • Matt Brubeck

          #5
          Re: Class instantiation question

          Todd Johnson <overdrive_ss@y ahoo.com> wrote:
          [color=blue]
          > 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?[/color]

          Here's one option:
          [color=blue][color=green][color=darkred]
          >>> class C:[/color][/color][/color]
          .... def __init__(self, a):
          .... self.a = int(a)
          ....[color=blue][color=green][color=darkred]
          >>> c = C("hello")[/color][/color][/color]
          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:
          [color=blue][color=green][color=darkred]
          >>> try: c = C("hello")[/color][/color][/color]
          .... except ValueError: c = None
          ....[color=blue][color=green][color=darkred]
          >>> print c[/color][/color][/color]
          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:
          [color=blue][color=green][color=darkred]
          >>> class C(object):[/color][/color][/color]
          .... def __new__(cls, a):
          .... try: a = int(a)
          .... except ValueError: return None
          .... return object.__new__( cls, a)
          .... def __init__(self, a):
          .... self.a = a
          ....[color=blue][color=green][color=darkred]
          >>> c = C(1)
          >>> c.a[/color][/color][/color]
          1[color=blue][color=green][color=darkred]
          >>> c = C("hello")
          >>> print c[/color][/color][/color]
          None

          Comment

          • Alex Martelli

            #6
            Re: Class instantiation question

            Todd Johnson wrote:
            [color=blue]
            > 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[/color]

            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.
            [color=blue]
            > 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?[/color]

            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(resu lt, 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



            Comment

            Working...