annoying behavior

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Elbert Lev

    annoying behavior

    # here is the problem I ran into:

    class foo:
    def __init__(self, host):
    self.f()
    self.r = True

    def f(self):
    if self.r:
    #<do something>
    pass
    else:
    #<do something else>
    pass

    f = foo("1234")

    #here is the output:

    #Traceback (most recent call last):
    # File "G:\MyProjects\ Python\Little\i nconv.py", line 16, in ?
    # f = foo("1234")
    # File "G:\MyProjects\ Python\Little\i nconv.py", line 5, in __init__
    # self.f()
    # File "G:\MyProjects\ Python\Little\i nconv.py", line 9, in f
    # if self.r:
    #AttributeError : foo instance has no attribute 'r'

    # I understand why does this happen, but, to tell the truth,
    # this feature is very annoying.
    # Are there any plans to relax this restriction?
    # In 3.0 :)?
  • Peter Hansen

    #2
    Re: annoying behavior

    Elbert Lev wrote:[color=blue]
    > # here is the problem I ran into:[/color]
    [code that uses a name before it's bound to anything][color=blue]
    > #here is the output:
    > #AttributeError : foo instance has no attribute 'r'
    >
    > # I understand why does this happen, but, to tell the truth,
    > # this feature is very annoying.
    > # Are there any plans to relax this restriction?
    > # In 3.0 :)?[/color]

    Uh, what feature? You have a bug in your code. What
    you showed is *no* different than doing this and
    expecting something other than an error:
    [color=blue][color=green][color=darkred]
    >>> print x
    >>> x = 5[/color][/color][/color]

    Please explain in more detail why you think this
    shouldn't be giving an error, and what output you
    think it should have given you.

    -Peter

    Comment

    • Dave Brueck

      #3
      Re: annoying behavior

      Elbert Lev wrote:[color=blue]
      > # here is the problem I ran into:
      >
      > class foo:
      > def __init__(self, host):
      > self.f()
      > self.r = True[/color]
      [snip code using attribute before it existed][color=blue]
      > #here is the output:
      > #AttributeError : foo instance has no attribute 'r'
      >
      > # I understand why does this happen, but, to tell the truth,
      > # this feature is very annoying.[/color]

      This "feature" is pretty useful! :)
      [color=blue]
      > # Are there any plans to relax this restriction?
      > # In 3.0 :)?[/color]

      Goodness, I sure hope not! (and I doubt it too) What behavior do you have in
      mind? Anything different than the current behavior would be confusing/misleading
      and would hide bugs like the one you encountered.

      -Dave

      Comment

      • Jeremy Jones

        #4
        Re: annoying behavior

        Elbert Lev wrote:
        [color=blue]
        ># here is the problem I ran into:
        >
        >class foo:
        > def __init__(self, host):
        > self.f()
        > self.r = True
        >
        > def f(self):
        > if self.r:
        > #<do something>
        > pass
        > else:
        > #<do something else>
        > pass
        >
        >f = foo("1234")
        >
        >#here is the output:
        >
        >#Traceback (most recent call last):
        ># File "G:\MyProjects\ Python\Little\i nconv.py", line 16, in ?
        ># f = foo("1234")
        ># File "G:\MyProjects\ Python\Little\i nconv.py", line 5, in __init__
        ># self.f()
        ># File "G:\MyProjects\ Python\Little\i nconv.py", line 9, in f
        ># if self.r:
        >#AttributeErro r: foo instance has no attribute 'r'
        >
        ># I understand why does this happen, but, to tell the truth,
        ># this feature is very annoying.
        ># Are there any plans to relax this restriction?
        ># In 3.0 :)?
        >
        >[/color]
        Relax what restriction? Why should this behave any differently than it
        is? I would kind of equate the above code to:
        [color=blue][color=green][color=darkred]
        >>> f = {}
        >>> f['a'][/color][/color][/color]
        Traceback (most recent call last):
        File "<stdin>", line 1, in ?
        KeyError: 'a'[color=blue][color=green][color=darkred]
        >>> f['a'] = 1[/color][/color][/color]


        How should Python know that I'm going to assign f['a'] to anything
        before it gets assigned? That's like expecting this:
        [color=blue][color=green][color=darkred]
        >>> f = {}
        >>> f['a']
        >>> #I'm planning on setting f['a'] to something in a little bit -[/color][/color][/color]
        maybe the Python interpreter can figure out what I'm going to do....
        1[color=blue][color=green][color=darkred]
        >>> f['a'] = 1[/color][/color][/color]

        to produce the results that I just typed in. You're calling method f()
        before you are setting attribute r to anything, so when you call f(),
        attribute r isn't set, so you get an exception. What restriction do you
        want to relax? Do you want the Python interpreter to read ahead and
        figure out if you were intending to set a variable and then use some
        variable that you were planning on setting in the future? If so, what
        if you set it and then set it again? Which one should it choose?

        Jeremy

        Comment

        • Peter Otten

          #5
          Re: annoying behavior

          Elbert Lev wrote:
          [color=blue]
          > # here is the problem I ran into:
          >
          > class foo:
          > def __init__(self, host):
          > self.f()
          > self.r = True
          >
          > def f(self):
          > if self.r:
          > #<do something>
          > pass
          > else:
          > #<do something else>
          > pass
          >
          > f = foo("1234")
          >
          > #here is the output:
          >
          > #Traceback (most recent call last):
          > # File "G:\MyProjects\ Python\Little\i nconv.py", line 16, in ?
          > # f = foo("1234")
          > # File "G:\MyProjects\ Python\Little\i nconv.py", line 5, in __init__
          > # self.f()
          > # File "G:\MyProjects\ Python\Little\i nconv.py", line 9, in f
          > # if self.r:
          > #AttributeError : foo instance has no attribute 'r'
          >
          > # I understand why does this happen, but, to tell the truth,[/color]

          ....you don't seem to. An attribute is not there until you set it.
          [color=blue]
          > # this feature is very annoying.
          > # Are there any plans to relax this restriction?
          > # In 3.0 :)?[/color]

          No chance. Even as a non-developer I dare say that.
          Either modify __init__():

          def __init__(self):
          self.r = False # for example
          self.f()
          self.r = True

          or change f():

          def f(self):
          if hasattr(self, "r"):
          # do something
          else:
          # do something else

          Peter

          Comment

          • Daniel Dittmar

            #6
            Re: annoying behavior

            Elbert Lev wrote:[color=blue]
            > # I understand why does this happen, but, to tell the truth,
            > # this feature is very annoying.
            > # Are there any plans to relax this restriction?
            > # In 3.0 :)?[/color]

            You can relax this restriction yourself:
            class foo:
            r = None
            def __init__(self, host):
            self.f()
            self.r = True

            or if you prefer Perl-style attribute access:
            class foo:
            def __init__(self, host):
            self.f()
            self.r = True

            def __getattr__ (self, name):
            return None

            and I'm sure metaclasses could also be used to good effect.

            Daniel

            Comment

            • Larry Bates

              #7
              Re: annoying behavior

              Elbert Lev wrote:[color=blue]
              > # here is the problem I ran into:
              >
              > class foo:
              > def __init__(self, host):
              > self.f()
              > self.r = True
              >
              > def f(self):
              > if self.r:
              > #<do something>
              > pass
              > else:
              > #<do something else>
              > pass
              >
              > f = foo("1234")
              >
              > #here is the output:
              >
              > #Traceback (most recent call last):
              > # File "G:\MyProjects\ Python\Little\i nconv.py", line 16, in ?
              > # f = foo("1234")
              > # File "G:\MyProjects\ Python\Little\i nconv.py", line 5, in __init__
              > # self.f()
              > # File "G:\MyProjects\ Python\Little\i nconv.py", line 9, in f
              > # if self.r:
              > #AttributeError : foo instance has no attribute 'r'
              >
              > # I understand why does this happen, but, to tell the truth,
              > # this feature is very annoying.
              > # Are there any plans to relax this restriction?
              > # In 3.0 :)?[/color]

              Just put the lines in the correct order:

              class foo:
              def __init__(self, host):
              self.r = True
              self.f()

              def f(self):
              if self.r:
              #<do something>
              pass
              else:
              #<do something else>
              pass

              f = foo("1234")

              You can't ask if self.r is True (which is what you do
              in the second line of the f() method) before it actually
              exists.

              Larry Bates
              Syscon, Inc.

              Comment

              • Guest's Avatar

                #8
                Re: annoying behavior


                ----- Original Message -----
                From: "Jeremy Jones" <zanesdad@bells outh.net>
                To: "Elbert Lev" <elbertlev@hotm ail.com>
                Cc: <python-list@python.org >
                Sent: Tuesday, September 28, 2004 1:13 PM
                Subject: Re: annoying behavior

                Jeremy!

                Sure it would be nice if a the interpreter would give a warning before
                really instantiating the instance of class foo (at least in "debug" mode).
                In my case the error happened after the program ran about 30 minutes. I do
                not think this is impossible.

                Comment

                • Elbert Lev

                  #9
                  Re: annoying behavior

                  Daniel Dittmar <daniel.dittmar @sap.corp> wrote in message news:<cjc61h$ag 0$1@news2.wdf.s ap.corp>...

                  I think, it would be good, if some sort of warning is given during
                  import, but not during instantiating the instance of the class. At
                  least in a "debug" mode. What really did happen: the bug was reported
                  after the scrip was running for 30 minutes. PyCheck finds it
                  immediatelly. Why not to do the same kind of check in the interpreter?

                  Comment

                  • Michael Hoffman

                    #10
                    Re: annoying behavior

                    Elbert Lev wrote:
                    [color=blue]
                    > I think, it would be good, if some sort of warning is given during
                    > import, but not during instantiating the instance of the class. At
                    > least in a "debug" mode. What really did happen: the bug was reported
                    > after the scrip was running for 30 minutes. PyCheck finds it
                    > immediatelly. Why not to do the same kind of check in the interpreter?[/color]

                    Can you post the results of your PyChecker run and the exact input to it?

                    I just did a test myself:

                    """
                    $ cat test1.py
                    class X(object):
                    def __init__(self):
                    self.f()
                    self.r = True

                    def f(self):
                    print self.r

                    def main():
                    x = X()

                    $ pychecker test1.py
                    Processing test1...

                    Warnings...

                    test1.py:10: Local variable (x) not used
                    """

                    I think that what you want the Python compiler to do is harder than you
                    think it is, and not all cases will be caught unless you actually run
                    the program.

                    I've forgotten to assign attributes and variables before using them in
                    the past--it's just something you have to learn not to do.
                    --
                    Michael Hoffman

                    Comment

                    • Dave Brueck

                      #11
                      Re: annoying behavior

                      Michael Hoffman wrote:[color=blue]
                      > Elbert Lev wrote:
                      >[color=green]
                      >> I think, it would be good, if some sort of warning is given during
                      >> import, but not during instantiating the instance of the class. At
                      >> least in a "debug" mode. What really did happen: the bug was reported
                      >> after the scrip was running for 30 minutes. PyCheck finds it
                      >> immediatelly. Why not to do the same kind of check in the interpreter?[/color]
                      >
                      >
                      > Can you post the results of your PyChecker run and the exact input to it?[/color]
                      [snip][color=blue]
                      > I think that what you want the Python compiler to do is harder than you
                      > think it is, and not all cases will be caught unless you actually run
                      > the program.[/color]

                      Also, it's not necessarily a mistake/bug, which is why it would make sense for
                      PyChecker to report it as a warning (if at all) and not the interpreter.

                      Comment

                      • Carlos Ribeiro

                        #12
                        Re: annoying behavior

                        On 28 Sep 2004 15:38:28 -0700, Elbert Lev <elbertlev@hotm ail.com> wrote:[color=blue]
                        > Daniel Dittmar <daniel.dittmar @sap.corp> wrote in message news:<cjc61h$ag 0$1@news2.wdf.s ap.corp>...
                        >
                        > I think, it would be good, if some sort of warning is given during
                        > import, but not during instantiating the instance of the class. At
                        > least in a "debug" mode. What really did happen: the bug was reported
                        > after the scrip was running for 30 minutes. PyCheck finds it
                        > immediatelly. Why not to do the same kind of check in the interpreter?[/color]

                        .... jumping in the discussion just to point out that you're now asking
                        for something reasonable, while on your first message you were asking
                        for the opposite -- to make the interpreter *less* restrict. It's no
                        wonder people answered like that...

                        BTW, the problem with pychecker, in my not-so-humble opinion, is that
                        it may be regarded as slow, or a little too obstrusive for continuous
                        usage. But that's my opinion anyway.

                        --
                        Carlos Ribeiro
                        Consultoria em Projetos
                        blog: http://rascunhosrotos.blogspot.com
                        blog: http://pythonnotes.blogspot.com
                        mail: carribeiro@gmai l.com
                        mail: carribeiro@yaho o.com

                        Comment

                        • Steve Holden

                          #13
                          Re: annoying behavior

                          elbertlev@hotma il.com wrote:
                          [color=blue]
                          > ----- Original Message -----
                          > From: "Jeremy Jones" <zanesdad@bells outh.net>
                          > To: "Elbert Lev" <elbertlev@hotm ail.com>
                          > Cc: <python-list@python.org >
                          > Sent: Tuesday, September 28, 2004 1:13 PM
                          > Subject: Re: annoying behavior
                          >
                          > Jeremy!
                          >
                          > Sure it would be nice if a the interpreter would give a warning before
                          > really instantiating the instance of class foo (at least in "debug" mode).
                          > In my case the error happened after the program ran about 30 minutes. I do
                          > not think this is impossible.[/color]

                          If not thinking something impossible actually made it possible then it
                          would be possible for me to ignore this thread rather than responding to it.

                          Next you'll be asking us to modify the compiler so it produces an error
                          if someone feeds it a program that never terminates.

                          If your program ran for 30 minutes before this quite-obvious bug
                          appeared then I should suggest you do some serious reading on the
                          subjects of unit-testing and test-first programming.

                          Alternatively, look for a language with DWIM-mode :-)

                          regards
                          Steve

                          Comment

                          • Jeremy Jones

                            #14
                            Re: annoying behavior

                            Steve Holden wrote:
                            [color=blue]
                            > elbertlev@hotma il.com wrote:
                            >[color=green]
                            >> ----- Original Message -----
                            >> From: "Jeremy Jones" <zanesdad@bells outh.net>
                            >> To: "Elbert Lev" <elbertlev@hotm ail.com>
                            >> Cc: <python-list@python.org >
                            >> Sent: Tuesday, September 28, 2004 1:13 PM
                            >> Subject: Re: annoying behavior
                            >>
                            >> Jeremy!
                            >>
                            >> Sure it would be nice if a the interpreter would give a warning before
                            >> really instantiating the instance of class foo (at least in "debug"
                            >> mode).
                            >> In my case the error happened after the program ran about 30 minutes.
                            >> I do
                            >> not think this is impossible.[/color]
                            >
                            >
                            > If not thinking something impossible actually made it possible then it
                            > would be possible for me to ignore this thread rather than responding
                            > to it.
                            >
                            > Next you'll be asking us to modify the compiler so it produces an
                            > error if someone feeds it a program that never terminates.
                            >
                            > If your program ran for 30 minutes before this quite-obvious bug
                            > appeared then I should suggest you do some serious reading on the
                            > subjects of unit-testing and test-first programming.
                            >
                            > Alternatively, look for a language with DWIM-mode :-)
                            >
                            > regards
                            > Steve[/color]

                            I'm going out on a limb here, but is it _possible_ that you imported the
                            module that contained the offending class, then 30 minutes later an
                            instance of said offending class was created? Here's your response to
                            Daniel Dittmar:

                            I think, it would be good, if some sort of warning is given during
                            import, but not during instantiating the instance of the class. At
                            least in a "debug" mode. What really did happen: the bug was reported
                            after the scrip was running for 30 minutes. PyCheck finds it
                            immediatelly. Why not to do the same kind of check in the interpreter?

                            Here, you're complaining about no warning being given at import. This
                            error would not have been manifest at import time, but at instantiation
                            time. And to your point, "It would be nice for the interpreter to give
                            a warning before really creating an instance of the class, at least in
                            debug....".... I recommend that you take Steves advice on unit testing.
                            Or, you could put try: except: blocks around every instance of any class
                            you create :-) No, it is _not_ impossible for the interpreter to do
                            that, but what all do you want it to check? Maybe I want it to call all
                            of my methods with some parameters specified somehow in docstrings and
                            make sure no errors occur. What you're asking is really general. Too
                            general, I think, for new functionality to be placed in the
                            interpreter. Thus Steve's recommendation for unit testing. If you
                            write good unit tests, there's your verification in "debug" mode. You
                            run your tests as you're developing. That way, you can target your
                            specific needs and you don't pay _any_ penalty at runtime.

                            Jeremy

                            Comment

                            • Patrick Maupin

                              #15
                              Re: annoying behavior

                              <elbertlev@hotm ail.com> wrote:[color=blue]
                              >
                              > Jeremy!
                              >
                              > Sure it would be nice if a the interpreter would give a warning before
                              > really instantiating the instance of class foo (at least in "debug" mode).
                              > In my case the error happened after the program ran about 30 minutes. I do
                              > not think this is impossible.[/color]

                              But, in Python, instances are "open". This means that I can add
                              attributes to a class instance at _any_ time (well, if I don't use
                              __slots__). The classes are open, too. I could even add attributes
                              to the class definition, after import, and before creating any
                              instances of the class.

                              This openness allows for the creation of some really powerful
                              programs. It also allows for the creation of some really powerful
                              bugs, which is why you are being admonished to run unit tests.

                              One thing this openness makes very difficult is the sort of static
                              semantic check you seem to think the compiler should perform. If I
                              can add a variable to the class after I import it but before I
                              instantiate it, how would a checker know if it was a bug or not?
                              (This is not to say that there are not programs which can flag such
                              constructs as "suspect", and you are certainly free to use such
                              programs to improve your own code, but please don't attempt to foist
                              the rigors of a statically declared language on Python -- a lot of its
                              practitioners are escapees from such rigorous straightjackets .)

                              One quasi-rhetorical question, though -- I haven't used C++ in awhile
                              (and I've never used Java). Are the stock compilers actually powerful
                              enough to flag this sort of inter-method use of an instance member
                              variable before it has been initialized? If so, color me edified. If
                              not, why are you complaining that Python didn't find this soon enough,
                              rather than praising Python for finding it at all? Personally, I
                              would much rather debug from such a clean description of what went
                              wrong than go rummaging around the typical core dump you could get
                              from an uninitialized pointer in another language.

                              Regards,
                              Pat

                              Comment

                              Working...