Built-in functions and keyword arguments

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Armando Serrano Lombillo

    Built-in functions and keyword arguments

    Why does Python give an error when I try to do this:
    >>len(object=[1,2])
    Traceback (most recent call last):
    File "<pyshell#4 0>", line 1, in <module>
    len(object=[1,2])
    TypeError: len() takes no keyword arguments

    but not when I use a "normal" function:
    >>def my_len(object):
    return len(object)
    >>my_len(object =[1,2])
    2

  • Duncan Booth

    #2
    Re: Built-in functions and keyword arguments

    Armando Serrano Lombillo <arserlom@gmail .comwrote:
    Why does Python give an error when I try to do this:
    >
    >>>len(object =[1,2])
    Traceback (most recent call last):
    File "<pyshell#4 0>", line 1, in <module>
    len(object=[1,2])
    TypeError: len() takes no keyword arguments
    >
    but not when I use a "normal" function:
    >
    >>>def my_len(object):
    return len(object)
    >
    >>>my_len(objec t=[1,2])
    2
    >
    At the C level there are several options for how you define a function
    callable from Python. The most general form is
    METH_VARARGS|ME TH_KEYWORDS which accepts both a tuple of arguments and a
    dictionary of keyword arguments. These then have to be parsed to find
    the actual arguments.

    Many of the builtin functions use only METH_VARARGS which means they
    don't support keyword arguments. "len" is even simpler and uses an
    option METH_O which means it gets a single object as an argument. This
    keeps the code very simple and may also make a slight difference to
    performance.

    I don't know if the reason that most builtin functions don't accept
    keywords is just historical (someone would have to go through a lot of
    code and add keyword argument names) or if there really is any
    measurable performance difference to not using the METH_KEYWORDS option.
    Being able to write less C code may be the main factor.

    Comment

    • Bruno Desthuilliers

      #3
      Re: Built-in functions and keyword arguments

      Armando Serrano Lombillo a écrit :
      Why does Python give an error when I try to do this:
      >
      >>>len(object =[1,2])
      Traceback (most recent call last):
      File "<pyshell#4 0>", line 1, in <module>
      len(object=[1,2])
      TypeError: len() takes no keyword arguments
      >
      but not when I use a "normal" function:
      >
      >>>def my_len(object):
      return len(object)
      >
      >>>my_len(objec t=[1,2])
      2
      In the second case, the name of the argument *is* 'object'. Which is not
      the case for the builtin len (which, fwiw, has type
      'builtin_functi on_or_method', not 'function', so inspect.getargs pec
      couldn't tell me more).

      <ot>
      While we're at it, you should avoid using builtin's names for
      identifiers - here, using 'object' as the arg name shadows the builtin
      'object' class).
      </ot>

      Comment

      • Steven D'Aprano

        #4
        Re: Built-in functions and keyword arguments

        On Mon, 29 Oct 2007 13:52:04 +0000, Armando Serrano Lombillo wrote:
        Why does Python give an error when I try to do this:
        >
        >>>len(object =[1,2])
        Traceback (most recent call last):
        File "<pyshell#4 0>", line 1, in <module>
        len(object=[1,2])
        TypeError: len() takes no keyword arguments
        >
        but not when I use a "normal" function:
        >
        >>>def my_len(object):
        return len(object)
        >
        >>>my_len(objec t=[1,2])
        2
        Because len() takes no keyword arguments, just like it says, but my_len()
        is written so it DOES take a keyword argument.

        When you call a function foo(object=[1,2]) you are instructing Python to
        bind the value [1,2] to the keyword argument "object". But if the
        function doesn't have a keyword argument named "object" then it will fail
        immediately. Since len() doesn't have ANY keyword arguments, naturally it
        doesn't have one called "object".

        You can see the same effect here:
        >>def my_len2(*args):
        .... return len(arg[0])
        ....
        >>my_len2(objec t=[1,2])
        Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        TypeError: my_len2() got an unexpected keyword argument 'object'


        Apart from the error message being slightly different, many (most? all?)
        of the built in functions are like my_len2().

        You may be thinking that keyword arguments are the equivalent of this:

        object=[1,2]
        len(object)

        That is not the case. They are not at all equivalent.



        --
        Steven.

        Comment

        • Duncan Booth

          #5
          Re: Built-in functions and keyword arguments

          Bruno Desthuilliers <bruno.42.desth uilliers@wtf.we bsiteburo.oops. com>
          wrote:
          In the second case, the name of the argument *is* 'object'. Which is not
          the case for the builtin len (which, fwiw, has type
          'builtin_functi on_or_method', not 'function', so inspect.getargs pec
          couldn't tell me more).
          >
          ><ot>
          While we're at it, you should avoid using builtin's names for
          identifiers - here, using 'object' as the arg name shadows the builtin
          'object' class).
          ></ot>
          I think you are being a little bit unfair here: help(len) says:

          len(...)
          len(object) -integer

          Return the number of items of a sequence or mapping.

          which implies that the argument to len has the name 'object' (although in
          fact it doesn't have a name). The OP was simply asking about the difference
          in calling conventions, not proposing to write code using 'object' as the
          argument name.

          Comment

          • Tim Chase

            #6
            Re: Built-in functions and keyword arguments

            ><ot>
            >While we're at it, you should avoid using builtin's names for
            >identifiers - here, using 'object' as the arg name shadows the builtin
            >'object' class).
            ></ot>
            >
            I think you are being a little bit unfair here: help(len) says:
            >
            len(...)
            len(object) -integer
            >
            Return the number of items of a sequence or mapping.
            >
            which implies that the argument to len has the name 'object' (although in
            fact it doesn't have a name).
            And to confound matters even further for the uninitiated,



            says that it's "len(s)" instead (but "len(s=[])" doesn't work either)

            -tkc




            Comment

            • Armando Serrano Lombillo

              #7
              Re: Built-in functions and keyword arguments

              On Oct 29, 3:10 pm, Duncan Booth <duncan.bo...@i nvalid.invalidw rote:
              Armando Serrano Lombillo <arser...@gmail .comwrote:
              >
              >
              >
              Why does Python give an error when I try to do this:
              >
              >>len(object=[1,2])
              Traceback (most recent call last):
              File "<pyshell#4 0>", line 1, in <module>
              len(object=[1,2])
              TypeError: len() takes no keyword arguments
              >
              but not when I use a "normal" function:
              >
              >>def my_len(object):
              return len(object)
              >
              >>my_len(object =[1,2])
              2
              >
              At the C level there are several options for how you define a function
              callable from Python. The most general form is
              METH_VARARGS|ME TH_KEYWORDS which accepts both a tuple of arguments and a
              dictionary of keyword arguments. These then have to be parsed to find
              the actual arguments.
              >
              Many of the builtin functions use only METH_VARARGS which means they
              don't support keyword arguments. "len" is even simpler and uses an
              option METH_O which means it gets a single object as an argument. This
              keeps the code very simple and may also make a slight difference to
              performance.
              >
              I don't know if the reason that most builtin functions don't accept
              keywords is just historical (someone would have to go through a lot of
              code and add keyword argument names) or if there really is any
              measurable performance difference to not using the METH_KEYWORDS option.
              Being able to write less C code may be the main factor.
              Ok. I was suspecting something like this. Performance issues aside, I
              think it would be a good idea if built-in functions behaved exactly
              the same as normal functions.

              BTW, I came into this problem when trying to use functools.parti al:

              import functools
              getattrF = functools.parti al(getattr, default=False)

              which I think should have worked if getattr behaved as normal
              functions do.

              In the end I did:

              def getattrF(object , name):
              return getattr(object, name, False)

              Any better idea?

              Comment

              • Armando Serrano Lombillo

                #8
                Re: Built-in functions and keyword arguments

                On Oct 29, 3:20 pm, Bruno Desthuilliers <bruno.
                42.desthuilli.. .@wtf.websitebu ro.oops.comwrot e:
                Armando Serrano Lombillo a écrit :
                >
                Why does Python give an error when I try to do this:
                >
                >>len(object=[1,2])
                Traceback (most recent call last):
                File "<pyshell#4 0>", line 1, in <module>
                len(object=[1,2])
                TypeError: len() takes no keyword arguments
                >
                but not when I use a "normal" function:
                >
                >>def my_len(object):
                return len(object)
                >
                >>my_len(object =[1,2])
                2
                >
                In the second case, the name of the argument *is* 'object'. Which is not
                the case for the builtin len (which, fwiw, has type
                'builtin_functi on_or_method', not 'function', so inspect.getargs pec
                couldn't tell me more).
                so that's the point, built-in functions don't behave as normal
                functions.
                <ot>
                While we're at it, you should avoid using builtin's names for
                identifiers - here, using 'object' as the arg name shadows the builtin
                'object' class).
                </ot>
                As Duncan points out, I was using the name object because it's what
                you get when you type help(len) (or in the calltips, or in). Anyway, I
                don't think there's any harm in overriding a builtin name in such a
                small scope (the object=[1,2] won't shadow the built-in object outside
                of the function).

                Comment

                • Marc 'BlackJack' Rintsch

                  #9
                  Re: Built-in functions and keyword arguments

                  On Mon, 29 Oct 2007 08:34:58 -0700, Armando Serrano Lombillo wrote:
                  On Oct 29, 3:10 pm, Duncan Booth <duncan.bo...@i nvalid.invalidw rote:
                  >>
                  >I don't know if the reason that most builtin functions don't accept
                  >keywords is just historical (someone would have to go through a lot of
                  >code and add keyword argument names) or if there really is any
                  >measurable performance difference to not using the METH_KEYWORDS option.
                  >Being able to write less C code may be the main factor.
                  >
                  Ok. I was suspecting something like this. Performance issues aside, I
                  think it would be a good idea if built-in functions behaved exactly
                  the same as normal functions.
                  As Steven D'Aprano showed they behave like normal functions. Even pure
                  Python functions can have arguments without names:

                  def spam(*args):
                  pass

                  Ciao,
                  Marc 'BlackJack' Rintsch

                  Comment

                  • Hendrik van Rooyen

                    #10
                    Re: Built-in functions and keyword arguments

                    "Tim Chase" <python.list@ti m.thechases.com >
                    I think you are being a little bit unfair here: help(len) says:

                    len(...)
                    len(object) -integer

                    Return the number of items of a sequence or mapping.

                    which implies that the argument to len has the name 'object' (although in
                    fact it doesn't have a name).
                    >
                    And to confound matters even further for the uninitiated,
                    >

                    >
                    says that it's "len(s)" instead (but "len(s=[])" doesn't work either)
                    Looks like a gotcha to me - its the difference between a keyword
                    (master = 42) and an assignment (s='I am a string')

                    You just can't do that - how is the parser supposed to know that
                    the second one is an assignment and not a keyword?

                    len([]) should work, though.

                    - Hendrik

                    Comment

                    • Bruno Desthuilliers

                      #11
                      Re: Built-in functions and keyword arguments

                      Armando Serrano Lombillo a écrit :
                      On Oct 29, 3:20 pm, Bruno Desthuilliers <bruno.
                      42.desthuilli.. .@wtf.websitebu ro.oops.comwrot e:
                      >Armando Serrano Lombillo a écrit :
                      >>
                      >>Why does Python give an error when I try to do this:
                      >>>>>len(object =[1,2])
                      >>Traceback (most recent call last):
                      >> File "<pyshell#4 0>", line 1, in <module>
                      >> len(object=[1,2])
                      >>TypeError: len() takes no keyword arguments
                      >>but not when I use a "normal" function:
                      >>>>>def my_len(object):
                      >> return len(object)
                      >>>>>my_len(obj ect=[1,2])
                      >>2
                      >In the second case, the name of the argument *is* 'object'. Which is not
                      >the case for the builtin len (which, fwiw, has type
                      >'builtin_funct ion_or_method', not 'function', so inspect.getargs pec
                      >couldn't tell me more).
                      >
                      so that's the point, built-in functions don't behave as normal
                      functions.
                      ><ot>
                      >While we're at it, you should avoid using builtin's names for
                      >identifiers - here, using 'object' as the arg name shadows the builtin
                      >'object' class).
                      ></ot>
                      >
                      As Duncan points out, I was using the name object because it's what
                      you get when you type help(len)
                      That what I thought. But anyway, you're not the only person reading this
                      newsgroup, and there are a couple gotchas that are worth pointing out
                      for those who don't know yet.
                      >(or in the calltips, or in). Anyway, I
                      don't think there's any harm in overriding a builtin name in such a
                      small scope
                      In this specific case, possibly - because there are few chances you need
                      to get at the builtin object type here. Still, it's better to avoid
                      shadowing builtin names IMHO - if only for readability.

                      Comment

                      Working...