Invisible function attributes

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

    Invisible function attributes

    Python 2.3[color=blue][color=green][color=darkred]
    >>> def foo():[/color][/color][/color]
    .... foo.a = 1
    ....[color=blue][color=green][color=darkred]
    >>> vars(foo)[/color][/color][/color]
    {}[color=blue][color=green][color=darkred]
    >>> foo()
    >>> vars(foo)[/color][/color][/color]
    {'a': 1}[color=blue][color=green][color=darkred]
    >>>[/color][/color][/color]

    So it would appear that function attributes are not really
    there until the first call to the function. If that is the
    intended behaviour, it is really weird. I couldn't find any
    explicit discussion of this topic in the LRM.

    Thanks if anyone can shed some light on this,

    -- O.L.
  • Tom Lee

    #2
    Re: Invisible function attributes

    Olivier Lefevre wrote:
    [color=blue]
    > Python 2.3
    >[color=green][color=darkred]
    >>>>def foo():[/color][/color]
    >
    > ... foo.a = 1
    > ...
    >[color=green][color=darkred]
    >>>>vars(foo)[/color][/color]
    >
    > {}
    >[color=green][color=darkred]
    >>>>foo()
    >>>>vars(foo)[/color][/color]
    >
    > {'a': 1}
    >
    >
    > So it would appear that function attributes are not really
    > there until the first call to the function. If that is the
    > intended behaviour, it is really weird. I couldn't find any
    > explicit discussion of this topic in the LRM.
    >
    > Thanks if anyone can shed some light on this,
    >
    > -- O.L.[/color]

    Makes sense to me.

    The foo.a = 1 line should never be executed until foo() is executed.
    Thus, foo.a is never set before the call to foo.

    - TL

    Comment

    • Peter Otten

      #3
      Re: Invisible function attributes

      def foo():
      try:
      foo.a += 1 # executed every time you call the function
      except AttributeError:
      foo.a = 1 # set to one if it's not already there

      foo.b = 1 # executed once

      print vars(foo) # function body not yet called {'b': 1}

      for i in range(3):
      foo()
      print vars(foo)

      Loop output is

      {'a': 1, 'b': 1}
      {'a': 2, 'b': 1}
      {'a': 3, 'b': 1}

      That is all perfectly sane as code in the function body is never executed
      unless you call the function, whereas code on the module level is executed
      immediately as the module is imported. So put foo.attr = ... into the
      function body iff you want it to execute every time the function is
      invoked; otherwise put it into the module startup code, i. e. do not indent
      it.

      Peter

      Comment

      • Terry Reedy

        #4
        Re: Invisible function attributes


        "Olivier Lefevre" <lefevrol@yahoo .com> wrote in message
        news:51809ae4.0 309030715.7706c adb@posting.goo gle.com...[color=blue]
        > Python 2.3[color=green][color=darkred]
        > >>> def foo():[/color][/color]
        > ... foo.a = 1[/color]

        If you want foo to be attributed before it is called, move the setter
        outside the function.
        [color=blue][color=green][color=darkred]
        >>> def foo(): pass[/color][/color][/color]
        ....[color=blue][color=green][color=darkred]
        >>> foo.a = 1
        >>> vars(foo)[/color][/color][/color]
        {'a': 1}

        Terry J Reedy


        Comment

        • John J. Lee

          #5
          Re: Invisible function attributes

          lefevrol@yahoo. com (Olivier Lefevre) writes:
          [...][color=blue]
          > So it would appear that function attributes are not really
          > there until the first call to the function. If that is the[/color]

          Not function attributes in general, just those that are first assigned
          to in the function body. No special rule here, though, because...

          [color=blue]
          > intended behaviour, it is really weird. I couldn't find any
          > explicit discussion of this topic in the LRM.
          >
          > Thanks if anyone can shed some light on this,[/color]

          ....what I'm guessing you haven't figured out yet is that everything
          works like this in Python. For example, what might be called a 'class
          declaration' in other languages isn't really a declaration in Python,
          it's code that gets executed at runtime. Same is true of functions:

          if WANT_SPAM:
          def sayhello(): print "spam"
          else:
          def sayhello(): print "eggs"

          sayhello()


          And your foo.a = 1 isn't a declaration (Python doesn't have them,
          really), it's just an attribute assignment.


          John

          Comment

          • Olivier Lefevre

            #6
            Re: Invisible function attributes

            Thanks to all those who replied.
            [color=blue]
            > ...what I'm guessing you haven't figured out yet is that everything
            > works like this in Python.[/color]

            Very possibly. I am coming to python from Java and I want to investigate
            the weird stuff precisely because either it's a one-off (in which case
            I'll make a note to myself to ignore it and not use it) or it holds the
            key to what is specific about the language. I seem to have hit pay dirt
            with this one ;-)

            Nudged by the dot syntax, I was thinking of this function attribute as
            if it were a sort of class member (i.e., pretending for a while this
            function is a class) and, since functions can't have instances, treating
            it as a sort of static member of the function, which should be available
            as soon as declared. Obviously I got it all wrong. Instead, they work
            like local variables except that they "persist" after the function has
            exited. That still feels weird to me. What are they used for? Give me
            a compelling reason to have such a beast in the language.

            OTOH, does this behaviour have anything to do with so-called "futures"?

            -- O.L.

            Comment

            • John Roth

              #7
              Re: Invisible function attributes


              "Olivier Lefevre" <lefevrol@yahoo .com> wrote in message
              news:51809ae4.0 309040627.28d7a 075@posting.goo gle.com...[color=blue]
              > Thanks to all those who replied.
              >[color=green]
              > > ...what I'm guessing you haven't figured out yet is that everything
              > > works like this in Python.[/color]
              >
              > Very possibly. I am coming to python from Java and I want to investigate
              > the weird stuff precisely because either it's a one-off (in which case
              > I'll make a note to myself to ignore it and not use it) or it holds the
              > key to what is specific about the language. I seem to have hit pay dirt
              > with this one ;-)
              >
              > Nudged by the dot syntax, I was thinking of this function attribute as
              > if it were a sort of class member (i.e., pretending for a while this
              > function is a class) and, since functions can't have instances, treating
              > it as a sort of static member of the function, which should be available
              > as soon as declared. Obviously I got it all wrong. Instead, they work
              > like local variables except that they "persist" after the function has
              > exited. That still feels weird to me. What are they used for? Give me
              > a compelling reason to have such a beast in the language.[/color]

              I don't know of a really compelling reason, other than it simply
              works that way. Like everything else in the language, functions
              are objects, which means that they have a dictionary at their
              core. Therefore, functions can have attributes.

              The only use I can think of would be definitely advanced
              programming. Functions are first class objects, which means
              they can be rebound anywhere you want them. If you find
              a good reason to do that, then as an extension you might find
              a reason to add attributes to classify what you've got so you
              can manage the process.

              As I said, I'm reaching with this one...
              [color=blue]
              >
              > OTOH, does this behaviour have anything to do with so-called "futures"?[/color]

              No. Future is a feature so that experimental features can be added to the
              language in one release, and then made standard in a future release.

              John Roth[color=blue]
              >
              > -- O.L.[/color]


              Comment

              • Bob Gailer

                #8
                Re: Invisible function attributes

                Of course the inevitable question is why do you want to do this? Consider
                creating a class instead (with a __call__ method if you want to call the
                instance as a function).

                class Foo:
                a = 1 # pre-initialized property
                def __call__(self):
                print self.a

                foo = Foo()
                foo()
                # prints 1

                Bob Gailer
                bgailer@alum.rp i.edu
                303 442 2625


                ---
                Outgoing mail is certified Virus Free.
                Checked by AVG anti-virus system (http://www.grisoft.com).
                Version: 6.0.506 / Virus Database: 303 - Release Date: 8/1/2003

                Comment

                • Jacek Generowicz

                  #9
                  Re: Invisible function attributes

                  lefevrol@yahoo. com (Olivier Lefevre) writes:
                  [color=blue]
                  > Nudged by the dot syntax, I was thinking of this function attribute as
                  > if it were a sort of class member (i.e., pretending for a while this
                  > function is a class) and, since functions can't have instances, treating
                  > it as a sort of static member of the function, which should be available
                  > as soon as declared.[/color]

                  There is no declaration in Python; you just create attributes by
                  binding objects to names.
                  [color=blue]
                  > Obviously I got it all wrong. Instead, they work like local
                  > variables except that they "persist" after the function has exited.[/color]

                  Hmmm. No. Functions are first class objects, and you can dynamically
                  add attributes to them as you go along (as is the case for many, but
                  not all, other types of objects).

                  Do you realize that the foo identifier you used in your example is not
                  inextricably linked to any function whose name is foo? The name of a
                  function, and the variables to which it is bound are two different
                  concepts.

                  Consequently, the foo.a in the function body only _coincidentally _
                  refers to an attribute of the function in which it appears.

                  Consider:
                  [color=blue][color=green][color=darkred]
                  >>> def foo(arg): foo.a = arg[/color][/color][/color]
                  ....[color=blue][color=green][color=darkred]
                  >>> bar = foo # Now the function is known by two different names
                  >>> bar(3)
                  >>> foo.a[/color][/color][/color]
                  3[color=blue][color=green][color=darkred]
                  >>> foo = 1 # Now the function called "foo" can only be accessed via bar !
                  >>> bar(4)[/color][/color][/color]
                  Traceback (most recent call last):
                  File "<stdin>", line 1, in ?
                  File "<stdin>", line 1, in foo
                  TypeError: 'int' object has only read-only attributes (assign to .a)[color=blue][color=green][color=darkred]
                  >>> bar # I call it "bar", bit it thinks it's called "foo"[/color][/color][/color]
                  <function foo at 0x815e71c>[color=blue][color=green][color=darkred]
                  >>>[/color][/color][/color]

                  The error at "bar(4)" in the above should hint at the fact that the
                  "foo" in "foo.a" in the definition of the function foo, does not refer
                  to the function itself but to whatever object which happens to be
                  bound to the name "foo" at the time the function is being exectuted.
                  [color=blue]
                  > What are they used for? Give me a compelling reason to have such a
                  > beast in the language.[/color]

                  Now there's a good question :-) I haven't found a use for these
                  myself ... but then I haven't looked very hard for one.

                  Given that function attributes were added to the language (in version
                  2.1 or 2.2 ?), I guess someone felt a need for them, and Guido agreed.

                  Comment

                  • Olivier Lefevre

                    #10
                    Re: Invisible function attributes

                    > Python has no declarations, only executable statements.

                    I think this was the key to my confusion in this case.
                    [color=blue][color=green][color=darkred]
                    > >>> bar(4)[/color][/color]
                    > Traceback (most recent call last):
                    > TypeError: 'int' object has only read-only attributes (assign to .a)[/color]

                    The way I read this, it says that a was bound to the name foo,
                    not to the function foo stood for at the time of that function's
                    definition; you are saying as much. Thus "foo.a" has to be looked
                    up and resolved anew for each call. This must be costly. Why was
                    it done this way?

                    OTOH I read the func attr PEP and it says that they are
                    implemented via a dict inside the function object. If so,
                    shouldn't they be bound to the function object rather than
                    to its name?? Or is func_dict itself an attribute?

                    -- O.L.

                    Comment

                    • John J. Lee

                      #11
                      Re: Invisible function attributes

                      Crumbs, is this thread still running?

                      lefevrol@yahoo. com (Olivier Lefevre) writes:[color=blue][color=green]
                      > > Python has no declarations, only executable statements.[/color]
                      >
                      > I think this was the key to my confusion in this case.[/color]

                      Certainly part of it.

                      [color=blue][color=green][color=darkred]
                      > > >>> bar(4)[/color]
                      > > Traceback (most recent call last):
                      > > TypeError: 'int' object has only read-only attributes (assign to .a)[/color]
                      >
                      > The way I read this, it says that a was bound to the name foo,[/color]

                      I'm not sure what's in your mind, and I'm only looking at this one
                      message (the rest aren't in my newsreader) but that traceback says you
                      tried to assign to an attribute on an integer, like so:

                      3.a = "bananas"


                      Doesn't make a lot of sense!

                      (Of course, you probably were assigning to a named integer, not a
                      literal

                      foo = 3
                      foo.a = "bananas"
                      )

                      [...][color=blue]
                      > OTOH I read the func attr PEP and it says that they are
                      > implemented via a dict inside the function object. If so,
                      > shouldn't they be bound to the function object rather than
                      > to its name??[/color]

                      They are.

                      [color=blue]
                      > Or is func_dict itself an attribute?[/color]

                      It is.


                      John

                      Comment

                      Working...