getattr(foo, 'foobar') not the same as foo.foobar?

castironpi at gmail.com castironpi at gmail.com
Thu Mar 13 21:15:19 EDT 2008


On Mar 13, 7:45 pm, castiro... at gmail.com wrote:
> On Mar 13, 7:18 pm, Mel <mwil... at the-wire.com> wrote:
>
>
>
>
>
> > Diez B. Roggisch wrote:
> > >> My understanding is that foo.bar does *not* create a new object.
>
> > > Your understanding is not correct.
>
> > >>  All it
> > >> does is return the value of the bar attribute of object foo.  What new
> > >> object is being created?
>
> > > A bound method. This happens through the descriptor-protocol. Please see
> > > this example:
>
> > > class Foo(object):
> > >     def bar(self):
> > >         pass
>
> > > f = Foo()
> > > a = Foo.bar
> > > b = f.bar
> > > c = f.bar
>
> > > print a, b, c
> > > print id(b), id(c)
>
> > (What Diez said.)  From what I've seen, f.bar creates a bound method
> > object by taking the unbound method Foo.bar and binding its first
> > parameter with f.  This is a run-time operation because it's easy to
> > re-assign some other function to the name Foo.bar, and if you do, the
> > behaviour of f.bar() will change accordingly.
>
> > You can get some very useful effects from these kinds of games.  You
> > can make f into a file-like object, for example, with
>
> > import sys
> > f.write = sys.stdout.write
>
> > Here, f.write *is* a straight attribute of f, although it's a built-in
> > method of the file class.  It's still bound, in a way, to sys.stdout.
> >   I'm assuming that a different example could create an attribute of f
> > that's a bound method of some other object entirely.  I've verified
> > that f.write('howdy') prints 'howdy' on standard output.
>
> Accordingly,
>
> f.write= types.MethodType( sys.stdout.__class__.write, sys.stdout ).
>
> It depends on what you want the implicit first (self) to be-- f or
> sys.stdout.
>
> But how come this works?
>
> >>> import types
> >>> import sys
>
> >>> class C:
>
> ...     write= sys.stdout.write
> ...     def g( self ):
> ...             self.write( 'was in \'g\'\n' )
> ...>>> c= C()
> >>> c.g()
>
> was in 'g'
>
> Shouldn't 'write' be getting extra parameters?  Sounds fishy, not to
> mix metaphors.

Ah.  Because this doesn't.

>>> class C:
...     write= sys.stdout.__class__.write #<--
...     def g( self ):
...             self.write( 'was in \'g\'\n' )
...
>>> c= C()
>>> c.g()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in g
  File "c:\programs\python\lib\io.py", line 1236, in write
    if self.closed:
AttributeError: 'C' object has no attribute 'closed'
>>>

That is, because sys.stdout.write is -not- a user-defined function.
What it is, is a bound member function, and only the former is
converted/wrapped/bound*, as it is in the subsequent example.

*/ whatever.



More information about the Python-list mailing list