noob question: "TypeError" wrong number of args

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

    #1

    noob question: "TypeError" wrong number of args

    Hi guys

    Tried searching for a solution to this, but the error message is so
    generic, that I could not get any meaningfull results.

    Anyways - errormessage:
    ----------------------------------------------------
    TypeError: addFile() takes exactly 1 argument (2 given)
    ----------------------------------------------------

    The script is run with two args "arg1" and "arg2":
    ----------------------------------------------------
    import sys

    class KeyBase:
    def addFile(file):
    print "initialize the base with lines from this file"

    print "These are the args"
    print "Number of args %d" % len(sys.argv)
    print sys.argv
    print sys.version_inf o
    print sys.version

    f = sys.argv[1]
    print "f = '%s'" % f
    b = KeyBase()

    b.addFile(f)
    ----------------------------------------------------

    The output - including error message
    (looks like stdout and stderr are a bit out of sync...):
    ----------------------------------------------------
    These are the args
    Traceback (most recent call last):

    Number of args 3
    ['C:\\home\\<.. bla bla snip ...>\\bin\\test .py', 'arg1', 'arg2']
    (2, 4, 2, 'final', 0)
    2.4.2 (#67, Oct 30 2005, 16:11:18) [MSC v.1310 32 bit (Intel)]
    f = 'arg1'

    File "C:\Program Files\ActiveSta te Komodo
    3.5\lib\support \dbgp\pythonlib \dbgp\client.py ", line 1806, in runMain
    self.dbg.runfil e(debug_args[0], debug_args)
    File "C:\Program Files\ActiveSta te Komodo
    3.5\lib\support \dbgp\pythonlib \dbgp\client.py ", line 1529, in runfile
    h_execfile(file , args, module=main, tracer=self)
    File "C:\Program Files\ActiveSta te Komodo
    3.5\lib\support \dbgp\pythonlib \dbgp\client.py ", line 590, in __init__
    execfile(file, globals, locals)
    File "C:\home\hbille \projects\bc4ro m\bin\test.py", line 20, in
    __main__
    b.addFile(f)
    TypeError: addFile() takes exactly 1 argument (2 given)
    ----------------------------------------------------

    I'm running this inside ActiveState Komodo on WinXP.

    Hope one you wizards can give me pointers to either what I'm doing
    wrong or maybe advise me what to modify in my setup.

    Thank you!

    Regards,
    Holger

  • Fredrik Lundh

    #2
    Re: noob question: &quot;TypeError &quot; wrong number of args

    Holger wrote:
    [color=blue]
    > Tried searching for a solution to this, but the error message is so
    > generic, that I could not get any meaningfull results.
    >
    > Anyways - errormessage:
    > ----------------------------------------------------
    > TypeError: addFile() takes exactly 1 argument (2 given)
    > ----------------------------------------------------
    >
    > The script is run with two args "arg1" and "arg2":
    > ----------------------------------------------------
    > import sys
    >
    > class KeyBase:
    > def addFile(file):
    > print "initialize the base with lines from this file"[/color]

    when defining your own classes, you must spell out the "self"
    argument in your method definitions:

    def addFile(self, file):
    print "initialize the base with lines from this file"

    see:



    </F>



    Comment

    • Holger

      #3
      Re: noob question: &quot;TypeError &quot; wrong number of args

      oops, that was kinda embarrassing.
      But thx anyway :-)

      Comment

      • Ben Finney

        #4
        Re: noob question: &quot;TypeError &quot; wrong number of args

        "Holger" <ishoej@gmail.c om> writes:
        [color=blue]
        > ----------------------------------------------------
        > TypeError: addFile() takes exactly 1 argument (2 given)
        > ----------------------------------------------------
        >
        > ----------------------------------------------------
        > import sys
        >
        > class KeyBase:
        > def addFile(file):
        > print "initialize the base with lines from this file"[/color]

        You've misunderstood -- or never followed -- the tutorial, especially
        how Python does object methods. Please follow the whole tutorial
        through, understanding each example as you work through it. You'll
        then have a solid basis of knowledge to go on with.

        <URL:http://docs.python.org/tut/>

        --
        \ "We are not gonna be great; we are not gonna be amazing; we are |
        `\ gonna be *amazingly* amazing!" -- Zaphod Beeblebrox, _The |
        _o__) Hitch-Hiker's Guide To The Galaxy_, Douglas Adams |
        Ben Finney

        Comment

        • Holger

          #5
          Re: noob question: &quot;TypeError &quot; wrong number of args

          I guess I deserved that. :-(
          I *did* read the tutorial, but then I forgot and didn't notice...
          My brain is getting is slow - so thx for the friendly slap in the face
          ;-)

          Comment

          • Edward Elliott

            #6
            Re: noob question: &quot;TypeError &quot; wrong number of args

            Holger wrote:[color=blue]
            > oops, that was kinda embarrassing.[/color]

            It's really not. You got a completely unhelpful error message saying you
            passed 2 args when you only passed one explicitly. The fact the b is also
            an argument to b.addfile(f) is totally nonobvious until you know that 1) b
            is an object not a module*, and 2) objects pass references to themselves as
            the first argument to their methods. The syntax "b." is completely
            different from the syntax of any other type of parameter.

            The mismatch between the number of parameters declared in the method
            signature and the number of arguments actually passed is nonobvious,
            unintuitive, and would trip up anybody who didn't already know what was
            going on. It's ugly and confusing. It's definitely a wart on the
            langauge.

            Making people pass 'self' explicitly is stupid because it always has to be
            the first argument, leading to these kinds of mistakes. The compiler
            should handle it for you - and no, explicit is not *always* better than
            implicit, just often and perhaps usually. While it's easy to recognize
            once you know what's going on, that doesn't make it any less of a wart.

            * technically modules may be objects also, but in practice you don't declare
            self as a parameter to module functions

            Comment

            • Steve Holden

              #7
              Re: noob question: &quot;TypeError &quot; wrong number of args

              Edward Elliott wrote:[color=blue]
              > Holger wrote:
              >[color=green]
              >>oops, that was kinda embarrassing.[/color]
              >
              >
              > It's really not. You got a completely unhelpful error message saying you
              > passed 2 args when you only passed one explicitly. The fact the b is also
              > an argument to b.addfile(f) is totally nonobvious until you know that 1) b
              > is an object not a module*, and 2) objects pass references to themselves as
              > the first argument to their methods. The syntax "b." is completely
              > different from the syntax of any other type of parameter.
              >[/color]
              Specifically, perhaps it would be better to say "b is an instance of
              some Python class or type".

              Objects don't actually "pass references to themselves". The interpreter
              adds the bound instance as the first argument to a call on a bound method.

              I agree that the error message should probably be improved for the
              specific case of the wrong number of arguments to a bound method (and
              even more specifically when the number of arguments is out by exactly
              one - if there's one too many then self may have been omitted from the
              parameter list).
              [color=blue]
              > The mismatch between the number of parameters declared in the method
              > signature and the number of arguments actually passed is nonobvious,
              > unintuitive, and would trip up anybody who didn't already know what was
              > going on. It's ugly and confusing. It's definitely a wart on the
              > langauge.
              >[/color]
              Sorry, it's a wart on your brain. Read Guido's arguments in favor of an
              explicit self argument again before you assert this so confidently. It's
              certainly confusing to beginners, but there are actually quite sound
              reasons for it (see next paragraph).
              [color=blue]
              > Making people pass 'self' explicitly is stupid because it always has to be
              > the first argument, leading to these kinds of mistakes. The compiler
              > should handle it for you - and no, explicit is not *always* better than
              > implicit, just often and perhaps usually. While it's easy to recognize
              > once you know what's going on, that doesn't make it any less of a wart.
              >[/color]
              Hmm. I see. How would you then handle the use of unbound methods as
              first-class objects? If self is implicitly declared, that implies that
              methods can only be used when bound to instances. How, otherwise, would
              you have an instance call its superclass's __init__ method if it's no
              longer valid to say

              myClass(otherCl ass):
              def __init__(self):
              otherClass.__in it__(self)
              ...
              [color=blue]
              > * technically modules may be objects also, but in practice you don't declare
              > self as a parameter to module functions[/color]

              The reason you don't do that is because the functions in a module are
              functions in a module, not methods of (some instance of) a class.
              Modules not only "may be" objects, they *are* objects, but the functions
              defined in them aren't methods. What, in Python, *isn't* an object?

              regards
              Steve
              --
              Steve Holden +44 150 684 7255 +1 800 494 3119
              Holden Web LLC/Ltd http://www.holdenweb.com
              Love me, love my blog http://holdenweb.blogspot.com
              Recent Ramblings http://del.icio.us/steve.holden

              Comment

              • doobiz@gmail.com

                #8
                Re: noob question: &quot;TypeError &quot; wrong number of args

                Just my opinion, but I think the Guido tutorial on Classes is
                unintelligible unless you're coming from another OO language.

                But I found something else that looks promising that you may want to
                peek at:



                rd

                Comment

                • BartlebyScrivener

                  #9
                  Re: noob question: &quot;TypeError &quot; wrong number of args

                  No way. You didn't deserve it. Unless you came from another OO
                  language, the Guido tutorial on Classes is unintelligible. It assumes
                  way too much knowledge.

                  But I found something else that looks promising that you may want to
                  peek at:



                  rd

                  Reply

                  Comment

                  • Edward Elliott

                    #10
                    Re: noob question: &quot;TypeError &quot; wrong number of args

                    Steve Holden wrote:[color=blue]
                    > Objects don't actually "pass references to themselves". The interpreter
                    > adds the bound instance as the first argument to a call on a bound method.[/color]

                    Sure, if you want to get technical For that matter, objects don't actually
                    call their methods either -- the interpreter looks up the method name in a
                    function table and dispatches it. I don't see how shorthand talk about
                    objects as actors hurts anything unless we're implementing an interpreter.

                    [color=blue]
                    > Sorry, it's a wart on your brain.[/color]

                    Fine it's a wart on my brain. It's still a wart.
                    [color=blue]
                    > Read Guido's arguments in favor of an
                    > explicit self argument again before you assert this so confidently.[/color]

                    I would if I could find it. I'm sure he had good reasons, they may even
                    convince me. But from my current perspective I disagree.
                    [color=blue]
                    > It's
                    > certainly confusing to beginners, but there are actually quite sound
                    > reasons for it (see next paragraph).[/color]

                    While confusion for beginners is a problem, that's not such a big deal.
                    It's a trivial fix that they see once and remember forever. What I mind is
                    its ugliness, that the language makes me do work declaring self when it
                    knows damn well it won't like my code until I do what it wants (yes I'm
                    anthropomorphiz ing interpreters now). The interpreter works for me, I
                    don't work for it. Things it can figure out automatically, it should
                    handle.

                    [color=blue]
                    > Hmm. I see. How would you then handle the use of unbound methods as
                    > first-class objects? If self is implicitly declared, that implies that
                    > methods can only be used when bound to instances.[/color]

                    I fail to see the problem here. I'm taking about implicit declaration on
                    the receiving end. It sounds like you're talking about implicit passing on
                    the sending end. The two are orthogonal. I can declare
                    def amethod (a, b):
                    and have self received implicitly (i.e. get the object instance bound by the
                    interpreter to the name self). The sender still explicitly provides the
                    object instance, e.g.
                    obj.amethod (a,b)
                    or
                    class.amethod (obj, a, b)
                    IOW everything can still work exactly as it does now, only *without me
                    typing self* as the first parameter of every goddamn method I write. Does
                    that make sense?
                    [color=blue]
                    > How, otherwise, would
                    > you have an instance call its superclass's __init__ method if it's no
                    > longer valid to say
                    >
                    > myClass(otherCl ass):
                    > def __init__(self):
                    > otherClass.__in it__(self)
                    > ...
                    >[/color]

                    Like this:
                    myClass(otherCl ass):
                    def __init__():
                    otherClass.__in it__(self)

                    self is still there and still bound, I just don't have to type it out. The
                    interpreter knows where it goes and what it does, automate it already!
                    [color=blue][color=green]
                    >> * technically modules may be objects also, but in practice you don't
                    >> declare self as a parameter to module functions[/color]
                    >
                    > The reason you don't do that is because the functions in a module are
                    > functions in a module, not methods of (some instance of) a class.
                    > Modules not only "may be" objects, they *are* objects, but the functions
                    > defined in them aren't methods. What, in Python, *isn't* an object?[/color]

                    If it looks like a duck and it quacks like a duck... Functions and methods
                    look different in their declaration but the calling syntax is the same.
                    It's not obvious from the dot notation syntax where the 'self' argument
                    comes from. Some interpreter magic goes on behind the scenes. Great, I'm
                    all for it, now why not extend that magic a little bit further?

                    Comment

                    • bruno at modulix

                      #11
                      Re: noob question: &quot;TypeError &quot; wrong number of args

                      Edward Elliott wrote:[color=blue]
                      > Holger wrote:
                      >[color=green]
                      >>oops, that was kinda embarrassing.[/color]
                      >
                      >
                      > It's really not. You got a completely unhelpful error message saying you
                      > passed 2 args when you only passed one explicitly. The fact the b is also
                      > an argument to b.addfile(f) is totally nonobvious until you know that 1) b
                      > is an object not a module*, and 2) objects pass references to themselves as
                      > the first argument to their methods.[/color]

                      Nope. It's the MethodType object (a descriptor) that wraps the function
                      that do the job. The object itself is totally unaware of this.
                      [color=blue]
                      > The syntax "b." is completely
                      > different from the syntax of any other type of parameter.
                      >
                      > The mismatch between the number of parameters declared in the method
                      > signature and the number of arguments actually passed[/color]

                      There's no mismatch at this level. The arguments passed to the *function
                      *object wrapped by the method actually matches the *function* signature.
                      [color=blue]
                      > is nonobvious,
                      > unintuitive, and would trip up anybody who didn't already know what was
                      > going on. It's ugly and confusing. It's definitely a wart on the
                      > langauge.[/color]

                      I do agree that the error message is really unhelpful for newbies (now I
                      don't know how difficult/costly it would be to correct this).
                      [color=blue]
                      > Making people pass 'self'[/color]

                      s/self/the instance/
                      [color=blue]
                      > explicitly is stupid[/color]

                      No. It's actually a feature.

                      [color=blue]
                      > because it always has to be
                      > the first argument, leading to these kinds of mistakes. The compiler
                      > should handle it for you[/color]

                      I don't think this would be possible if we want to keep the full
                      dynamism of Python. How then could the compiler handle the following code ?

                      class MyObj(object):
                      def __init__(self, name):
                      self.name = name

                      def someFunc(obj):
                      try:
                      print obj.name
                      except AttributeError:
                      print "obj %s has no name" % obj

                      import types
                      m = MyObj('parrot')
                      m.someMeth = types.MethodTyp e(someFunc, obj, obj.__class__)
                      m.someMeth()
                      [color=blue]
                      > - and no, explicit is not *always* better than
                      > implicit, just often and perhaps usually. While it's easy to recognize
                      > once you know what's going on, that doesn't make it any less of a wart.
                      >
                      > * technically modules may be objects also,[/color]

                      s/may be/are/
                      [color=blue]
                      > but in practice you don't declare
                      > self as a parameter to module functions[/color]

                      def someOtherFunc() :
                      print "hello there"

                      m.someFunc = someOtherFunc
                      m.someFunc()


                      --
                      bruno desthuilliers
                      python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
                      p in 'onurb@xiludom. gro'.split('@')])"

                      Comment

                      • Edward Elliott

                        #12
                        Re: noob question: &quot;TypeError &quot; wrong number of args

                        bruno at modulix wrote:[color=blue][color=green]
                        >> that 1) b is an object not a module*, and 2) objects pass references to
                        >> themselves as the first argument to their methods.[/color]
                        >
                        > Nope. It's the MethodType object (a descriptor) that wraps the function
                        > that do the job. The object itself is totally unaware of this.[/color]

                        It's shorthand, not to be taken literally.

                        [color=blue][color=green]
                        >> Making people pass 'self'[/color]
                        >
                        > s/self/the instance/
                        >[color=green]
                        >> explicitly is stupid[/color]
                        >
                        > No. It's actually a feature.[/color]

                        potato, potahto.

                        [color=blue][color=green]
                        >> the first argument, leading to these kinds of mistakes. The compiler
                        >> should handle it for you[/color]
                        >
                        > I don't think this would be possible if we want to keep the full
                        > dynamism of Python. How then could the compiler handle the following code
                        > ?
                        >
                        > class MyObj(object):
                        > def __init__(self, name):
                        > self.name = name[/color]

                        class MyObj(object):
                        def __init__(name):
                        self.name = name

                        And the rest should work fine. When the interpreter sees a method
                        declaration, it can automatically 1) add the object instance parameter to
                        the signature, and 2) automatically bind the name self to the object
                        instance on dispatch. Everything else is just as before.
                        [color=blue][color=green]
                        >> but in practice you don't declare
                        >> self as a parameter to module functions[/color]
                        >
                        > def someOtherFunc() :
                        > print "hello there"
                        >
                        > m.someFunc = someOtherFunc
                        > m.someFunc()[/color]

                        Complete non-sequitor, what does this have to do with self?

                        Comment

                        • bruno at modulix

                          #13
                          Re: noob question: &quot;TypeError &quot; wrong number of args

                          Edward Elliott wrote:[color=blue]
                          > bruno at modulix wrote:
                          >[color=green][color=darkred]
                          >>>that 1) b is an object not a module*, and 2) objects pass references to
                          >>>themselves as the first argument to their methods.[/color]
                          >>
                          >>Nope. It's the MethodType object (a descriptor) that wraps the function
                          >>that do the job. The object itself is totally unaware of this.[/color]
                          >
                          >
                          > It's shorthand, not to be taken literally.
                          >[/color]

                          It is to be taken literally. Either you talk about how Python
                          effectively works or the whole discussion is useless.
                          [color=blue]
                          >[color=green][color=darkred]
                          >>>Making people pass 'self'[/color]
                          >>
                          >>s/self/the instance/
                          >>
                          >>[color=darkred]
                          >>>explicitly is stupid[/color]
                          >>
                          >>No. It's actually a feature.[/color]
                          >
                          > potato, potahto.
                          >[/color]

                          tss...
                          [color=blue]
                          >[color=green][color=darkred]
                          >>>the first argument, leading to these kinds of mistakes. The compiler
                          >>>should handle it for you[/color][/color]
                          >[color=green]
                          >>
                          >>I don't think this would be possible if we want to keep the full
                          >>dynamism of Python. How then could the compiler handle the following code
                          >>?
                          >>
                          >>class MyObj(object):
                          >> def __init__(self, name):
                          >> self.name = name[/color]
                          >
                          >
                          > class MyObj(object):
                          > def __init__(name):
                          > self.name = name[/color]

                          You skipped the interesting part, so I repost it and ask again: how
                          could the following code work without the instance being an explicit
                          parameter of the function to be used as a method ?

                          def someFunc(obj):
                          try:
                          print obj.name
                          except AttributeError:
                          print "obj %s has no name" % obj

                          import types
                          m = MyObj('parrot')
                          m.someMeth = types.MethodTyp e(someFunc, obj, obj.__class__)
                          m.someMeth()

                          You see, wrapping a function into a method is not done at compile-time,
                          but at runtime. And it can be done manually outside a class statement.
                          In the above example, someFunc() can be used as a plain function.

                          In fact, almost any existing function taking at least one argument can
                          be turned into a method (in theory at least - practically, you of course
                          need to make sure the first argument is of a compatible type). This
                          wouldn't work with some automagical injection of the instance in the
                          function's local namespace, because you would then have to write
                          "method"'s code diffently from function's code.
                          [color=blue]
                          > And the rest should work fine. When the interpreter sees a method
                          > declaration,[/color]

                          The interpreter never sees a 'method declaration', since there is no
                          such thing as a 'method declaration' in Python. The def statement
                          creates a *function* object:
                          [color=blue][color=green][color=darkred]
                          >>> class Parrot(object):[/color][/color][/color]
                          .... def test(self):
                          .... pass
                          .... print "type(test) is : ", type(test)
                          ....
                          type(test) is : <type 'function'>
                          [color=blue][color=green][color=darkred]
                          >>>but in practice you don't declare
                          >>>self as a parameter to module functions[/color]
                          >>
                          >>def someOtherFunc() :
                          >> print "hello there"
                          >>
                          >>m.someFunc = someOtherFunc
                          >>m.someFunc( )[/color]
                          >
                          > Complete non-sequitor, what does this have to do with self?[/color]

                          It has to do that the obj.name() syntax doesn't imply a *method* call -
                          it can as well be a plain function call. Also, and FWIW:[color=blue][color=green][color=darkred]
                          >>> def moduleFunc():[/color][/color][/color]
                          .... print self.name
                          ....[color=blue][color=green][color=darkred]
                          >>> moduleFunc()[/color][/color][/color]
                          Traceback (most recent call last):
                          File "<stdin>", line 1, in ?
                          File "<stdin>", line 2, in moduleFunc
                          NameError: global name 'self' is not defined[color=blue][color=green][color=darkred]
                          >>>[/color][/color][/color]



                          HTH
                          --
                          bruno desthuilliers
                          python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
                          p in 'onurb@xiludom. gro'.split('@')])"

                          Comment

                          • Edward Elliott

                            #14
                            Re: noob question: &quot;TypeError &quot; wrong number of args

                            bruno at modulix wrote:[color=blue]
                            > It is to be taken literally. Either you talk about how Python
                            > effectively works or the whole discussion is useless.[/color]

                            I started talking about the code-level view (programmer's perspective) so
                            shorthand was fine. Now that we've moved on to interpreter/compiler-level
                            stuff, I agree that more precision is warranted.
                            [color=blue]
                            > You skipped the interesting part, so I repost it and ask again: how
                            > could the following code work without the instance being an explicit
                            > parameter of the function to be used as a method ?
                            >
                            > def someFunc(obj):
                            > try:
                            > print obj.name
                            > except AttributeError:
                            > print "obj %s has no name" % obj
                            >
                            > import types
                            > m = MyObj('parrot')
                            > m.someMeth = types.MethodTyp e(someFunc, obj, obj.__class__)
                            > m.someMeth()[/color]

                            I posted the only part that needs modification. Here it is again with the
                            entire segment:

                            class MyObj(object):
                              def __init__(name):
                                self.name = name <== interpreter binds name 'self' to object instance.
                            compiler adds 'self' to method sig as 1st param.

                            def someFunc(obj):
                            try:
                            print obj.name <== 'obj' gets bound to first arg passed. when bound
                            as a method, first arg will be object instance.
                            when called as func, it will be first actual arg.
                            except AttributeError:
                            print "obj %s has no name" % obj

                            import types
                            m = MyObj('parrot')
                            m.someMeth = types.MethodTyp e(someFunc, obj, obj.__class__) <== binds obj
                            to first parameter of someFunc as usual
                            m.someMeth()

                            [color=blue]
                            > You see, wrapping a function into a method is not done at compile-time,
                            > but at runtime. And it can be done manually outside a class statement.
                            > In the above example, someFunc() can be used as a plain function.[/color]

                            All the parameter information has been preserved. Method signatures are
                            unchanged from their current form, so the interpreter has no trouble
                            deducing arguments. You just don't actually declare self yourself. When
                            binding a function to an object as above, the interpreter sees and does
                            exactly the same thing as now.
                            [color=blue]
                            > This
                            > wouldn't work with some automagical injection of the instance in the
                            > function's local namespace, because you would then have to write
                            > "method"'s code diffently from function's code.[/color]

                            Maybe this will make it clearer:

                            Programmer's view Compiler Interpreter's view
                            def func (a, b) func (a, b) -> func (a, b) func (a, b)
                            def method (a) method (a) -> method (self, a) method (self, a)

                            IOW the compiler adds 'self' to the front of the parameter list when
                            processing a method declaration. Interpreter sees the same signature as
                            now, only programmer doesn't have to write 'self' anymore.
                            [color=blue][color=green]
                            >> And the rest should work fine. When the interpreter sees a method
                            >> declaration,[/color]
                            >
                            > The interpreter never sees a 'method declaration', since there is no
                            > such thing as a 'method declaration' in Python. The def statement
                            > creates a *function* object:[/color]

                            Fine, whatever, compiler sees method declaration, interpreter sees function
                            object. The point is, the interpreter sees the same thing it does now.
                            [color=blue][color=green]
                            >> Complete non-sequitor, what does this have to do with self?[/color]
                            >
                            > It has to do that the obj.name() syntax doesn't imply a *method* call -
                            > it can as well be a plain function call.[/color]

                            Ok I see your point, but it doesn't matter because the interpreter sees the
                            same function object as before.

                            This confusion is partly (mostly? ;) my fault. I haven't been
                            distinguishing precisely between the interpreter and the compiler because
                            usually with Python it doesn't matter (in practice). This is clearly one
                            place it does. In the words of Douglas Adams: We apologize for the
                            inconvenience.

                            [color=blue]
                            > Also, and FWIW:[color=green][color=darkred]
                            >>>> def moduleFunc():[/color][/color]
                            > ... print self.name
                            > ...[color=green][color=darkred]
                            >>>> moduleFunc()[/color][/color]
                            > Traceback (most recent call last):
                            > NameError: global name 'self' is not defined[/color]

                            Exactly, that was my point in the first place.

                            Comment

                            • Bruno Desthuilliers

                              #15
                              Re: noob question: &quot;TypeError &quot; wrong number of args

                              Edward Elliott a écrit :[color=blue]
                              > bruno at modulix wrote:
                              >[/color]
                              (snip)[color=blue]
                              >[color=green]
                              >>You skipped the interesting part, so I repost it and ask again: how
                              >>could the following code work without the instance being an explicit
                              >>parameter of the function to be used as a method ?
                              >>
                              >>def someFunc(obj):
                              >> try:
                              >> print obj.name
                              >> except AttributeError:
                              >> print "obj %s has no name" % obj
                              >>
                              >>import types
                              >>m = MyObj('parrot')
                              >>m.someMeth = types.MethodTyp e(someFunc, obj, obj.__class__)
                              >>m.someMeth( )[/color]
                              >
                              >
                              > I posted the only part that needs modification.[/color]

                              Nope.
                              [color=blue]
                              > Here it is again with the
                              > entire segment:
                              >
                              > class MyObj(object):
                              > def __init__(name):
                              > self.name = name <== interpreter binds name 'self' to object instance.
                              > compiler adds 'self' to method sig as 1st param.
                              >
                              > def someFunc(obj):
                              > try:
                              > print obj.name <== 'obj' gets bound to first arg passed. when bound
                              > as a method, first arg will be object instance.
                              > when called as func, it will be first actual arg.
                              > except AttributeError:
                              > print "obj %s has no name" % obj
                              >
                              > import types
                              > m = MyObj('parrot')
                              > m.someMeth = types.MethodTyp e(someFunc, obj, obj.__class__) <== binds obj
                              > to first parameter of someFunc as usual
                              > m.someMeth()
                              >
                              >
                              >[color=green]
                              >>You see, wrapping a function into a method is not done at compile-time,
                              >>but at runtime. And it can be done manually outside a class statement.
                              >>In the above example, someFunc() can be used as a plain function.[/color]
                              >
                              >
                              > All the parameter information has been preserved.
                              > Method signatures are
                              > unchanged from their current form,
                              > so the interpreter has no trouble
                              > deducing arguments. You just don't actually declare self yourself.[/color]

                              In this exemple, it was named 'obj', to make clear that there was
                              nothing special about 'self'. As you can see from the call, I didn't
                              actually passed the fist param, since the method wrapper takes care of
                              it... So if we were to implement your proposition (which seems very
                              unlikely...), the above code *would not work* - we'd get a TypeError
                              because of the missing argument.
                              [color=blue]
                              > When
                              > binding a function to an object as above, the interpreter sees and does
                              > exactly the same thing as now.[/color]

                              I'm sorry, but you're just plain wrong. *Please* take time to read about
                              the descriptor protocol and understand Python's object model.
                              [color=blue]
                              >[color=green]
                              >>This
                              >>wouldn't work with some automagical injection of the instance in the
                              >>function's local namespace, because you would then have to write
                              >>"method"'s code diffently from function's code.[/color]
                              >
                              >
                              > Maybe this will make it clearer:
                              >
                              > Programmer's view Compiler Interpreter's view
                              > def func (a, b) func (a, b) -> func (a, b) func (a, b)
                              > def method (a) method (a) -> method (self, a) method (self, a)
                              >
                              > IOW the compiler adds 'self' to the front of the parameter list when
                              > processing a method declaration.[/color]

                              1/ there is *no* 'method declaration' in Python
                              2/ wrapping functions into methods happens at runtime, *not* at compile
                              time.

                              (snip)
                              [color=blue][color=green][color=darkred]
                              >>>And the rest should work fine. When the interpreter sees a method
                              >>>declaratio n,[/color]
                              >>
                              >>The interpreter never sees a 'method declaration', since there is no
                              >>such thing as a 'method declaration' in Python. The def statement
                              >>creates a *function* object:[/color]
                              >
                              >
                              > Fine, whatever, compiler sees method declaration,[/color]

                              There ain't *nothing* like a 'method declaration' in Python. Zilch,
                              nada, none, rien... All there is is the def statement that creates a
                              *function* (and the class statement that creates a class object).
                              [color=blue]
                              >[color=green][color=darkred]
                              >>>Complete non-sequitor, what does this have to do with self?[/color]
                              >>
                              >>It has to do that the obj.name() syntax doesn't imply a *method* call -
                              >>it can as well be a plain function call.[/color]
                              >
                              > Ok I see your point,[/color]

                              Not quite, I'm afraid.
                              [color=blue]
                              >[color=green]
                              >>Also, and FWIW:
                              >>[color=darkred]
                              >>>>>def moduleFunc():[/color]
                              >>
                              >>... print self.name
                              >>...
                              >>[color=darkred]
                              >>>>>moduleFunc ()[/color]
                              >>
                              >>Traceback (most recent call last):
                              >>NameError: global name 'self' is not defined[/color]
                              >
                              >
                              > Exactly, that was my point in the first place.[/color]

                              I'm afraid we don't understand each other here. This was supposed to
                              come as an illustration that, if some black magic was to 'inject' the
                              instance (here named 'self') in the local namespace of a 'method' (the
                              way you see it), we would loose the possibility to turn a function into
                              a method. Try to re-read both examples with s/obj/self/ in the first one
                              and s/self/obj/ in this last one.

                              Edward, I know I told you so at least three times, but really,
                              seriously, do *yourself* a favor : take time to read about descriptors
                              and metaclasses - and if possible to experiment a bit - so you can get a
                              better understanding of Python's object model. Then I'll be happy to
                              continue this discussion (.

                              FWIW, I too found at first that having to explicitely declare the
                              instance as first param of a 'function-to-be-used-as-a-method' was an
                              awful wart. And by that time (Python 1.5.2), it actually *was* a wart
                              IMVHO - just like the whole 'old-style-class' stuff should I say. But
                              since 'type-unification' and new-style-classes, the wart has turned into
                              a feature, even if this only become obvious once you get a good enough
                              understanding of how the whole damn thing works.

                              Following it's overall design philosophy, Python exposes (and so let you
                              take control of) almost any detail of the object model implementation.
                              The purpose here is to make simple things simple *and* complex things
                              possibles, and the mean is to have a restricted yet consistent set of
                              mechanisms. It may not be a jewel of pure beauty, but from a practical
                              POV, it ends up being more powerful than what you'll find in most
                              main-stream OOPLs - where simple things happens to be not so simple and
                              complex things sometime almost impossible - and yet much more usable
                              than some more powerful but somewhat cryptic OOPLs (like Common Lisp -
                              which is probably the most astonishing language ever) where almost
                              anything is possible but even the simplest things tend to be complex.

                              Oh, also - should I mention it here ? - Ruby is another pretty nice and
                              powerful OOPL, with a more 'pure' object model (at least at first sight
                              - I have not enough experience with it to know if it holds its
                              promises). While Python is My Favourite Language(tm), I'm not too much
                              religious about this, and can well understand that someone's feature is
                              someone else's wart - thanks the Lord, everyone is different and unique
                              -, and you may feel better with Ruby.

                              Comment

                              Working...