[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

Difference between 'function' and 'method'

??

3/4/2008 8:22:00 AM

Howdy everyone,

This is a big problem puzzles me for a long time. The core question is:
How to dynamically create methods on a class or an instance?

Let me state it step by step.
1.
def gunc(self):
pass
class A(object):
def func(self):
pass
a = A()
a.func # gives "bound method", type is "instancemethod"
A.func # gives "unbound method", type is "instancemethod"
gunc # gives "function", type if "function"

# ?? Does this line attach a method to instance? ... I don't think so.
a.gunc = gunc

I found stardard library 'new' may help. Is that right?

2.
a = A() # instance of old class A
# Do attach a new method to class A...
b = A() # instance of new class A
Does "a" can get the new method automatically?
Does new method have the *same* concept level with old methods?
Especially, if there
are classes inherit from class A, how does name resolution work on this case?

3.
How do I write a decroator for a method? Eg:
class A(object):
@my_dec
def func(self):
pass
Here, my_dec should return a method rathar than a function/lambda. Am I right?
What does @property @staticmethod... really do? I cannot step-into them for
source code.

4.
If most of above questions can be solved, then it would be easy to implement
the feature: "dynamic property attach".
Eg:
One class can read/store settings from/to some file based on
the file content.
# File: cfg.ini
x = 1
y = python
config = SettingClass('cfg.ini') # dynamically build up properties x and y.
x = config.x # x will be set to 1 (str -> int convertion would be
done by 'property x')
y = config.y # y will be set to 'python'
config.x = 9 # 'x = 9' is written to cfg.ini.

How to implement
^_^ Maybe there are some library does the same thing. What is it? How
to implement ?


Thank you for your attention!

---
ShenLei
19 Answers

Paul Boddie

3/4/2008 10:38:00 AM

0

On 4 Mar, 09:22, "??" <littlesweetme...@gmail.com> wrote:
>
> This is a big problem puzzles me for a long time. The core question is:
> How to dynamically create methods on a class or an instance?
>
> Let me state it step by step.
> 1.
> def gunc(self):
> pass
> class A(object):
> def func(self):
> pass
> a = A()
> a.func # gives "bound method", type is "instancemethod"
> A.func # gives "unbound method", type is "instancemethod"
> gunc # gives "function", type if "function"
>
> # ?? Does this line attach a method to instance? ... I don't think so.
> a.gunc = gunc

No, unfortunately not. You might get the detailed explanation from
someone else, but generally, you have to assign functions to classes;
these are then exposed as methods via instances of such classes.

A.gunc = gunc

> I found stardard library 'new' may help. Is that right?

Yes, it can help:

import new
a.gunc = new.instancemethod(gunc, a, A)

> 2.
> a = A() # instance of old class A
> # Do attach a new method to class A...
> b = A() # instance of new class A
> Does "a" can get the new method automatically?

Can "a" get the new method automatically? Apparently, yes:

class A:
pass

a = A()

def f(self, x):
print x

A.f = f
a.f(123) # works, printing 123

> Does new method have the *same* concept level with old methods?
> Especially, if there
> are classes inherit from class A, how does name resolution work on this case?

As far as I'm aware, after you've added a method to a class, instances
will regard the method like all the previously existing methods, since
method lookup is a dynamic operation.

I'll not address your other questions in this message since I'm not a
heavy user of decorators and don't want to provide a quick answer
without fully testing it first. However, it is important to remember
that the "magic" occurs for class attributes, not instance attributes.
So, for example, it's quite possible that you'd want to assign a
function to an instance attribute, but you wouldn't want the instance
to suddenly "own" that function...

def somefunc(x, y):
# Do something with x and y...
return x + y

a = A()
a.somefunc = somefunc # store the function somewhere

# Later...

adder = a.somefunc

# Later still...

result = adder(p, q) # wouldn't work if somefunc became a method

Python seems to do the most intuitive thing, I think, but it's quite
tricky to contemplate all the implications.

Paul

P.S. I can never really remember all the different situations and
outcomes with method assignment, but then it's something I hardly ever
do. I'd be interested to know whether my situation is unusual, however.

Bruno Desthuilliers

3/4/2008 11:28:00 AM

0

?? a écrit :
> Howdy everyone,
>
> This is a big problem puzzles me for a long time. The core question is:
> How to dynamically create methods on a class or an instance?

class Foo(object):
pass

def bar(self, arg):
print "in bar : self == % - arg == %s" % (self, str(arg))

def baaz(self, arg):
print "in baaz : self == % - arg == %s" % (self, str(arg))


f = Foo()

# adding bar as a method to class Foo
Foo.bar = bar

# f now can use bar:
f.bar(42)

# as well as new instances of Foo, of course
g = Foo()
g.bar()

# adding baaz as a method to f, the old way:
import new
f.baaz = new.instancemethod(baaz, f, type(f))

f.baaz()

# adding baaz as a method to g, the other way:
g.baaz = baaz.__get__(g, type(g))

g.baaz()


> Let me state it step by step.
> 1.
> def gunc(self):
> pass
> class A(object):
> def func(self):
> pass
> a = A()
> a.func # gives "bound method", type is "instancemethod"
> A.func # gives "unbound method", type is "instancemethod"
> gunc # gives "function", type if "function"
>
> # ?? Does this line attach a method to instance? ... I don't think so.
> a.gunc = gunc

It doesn't.


> I found stardard library 'new' may help. Is that right?

cf above. If you work with old-style classes, you'll need
new.instancemethod.

> 2.
> a = A() # instance of old class A
> # Do attach a new method to class A...
> b = A() # instance of new class A
> Does "a" can get the new method automatically?

Yes. In Python, a class is itself an object, and is an attribute of it's
instances (instance.__class__). Names are resolved at runtime, and
attributes not found in the instance's __dict__ are looked up in the
class (and then in the superclasses etc).

> Does new method have the *same* concept level with old methods?

The newly added method works exactly the same way as already existing
ones. Not a single difference. The class statement is just syntactic
sugar anyway. The following snippets are equivalent:

# sugar-coated:
class Boo(object):
faaz = 0

def far(self):
type(self).faaz += 1
print self

def frob(self):
print "yadda"

# raw:
def far(self):
type(self).faaz += 1
print self

Boo = type('Boo', (object,), dict(faaz=0, far=far))

def frob(self):
print "yadda"

Boo.frob = frob

> Especially, if there
> are classes inherit from class A, how does name resolution work on this case?

As usual.

> 3.
> How do I write a decroator for a method?

Mostly the same way you'd write a decorator for a function

> Eg:
> class A(object):
> @my_dec
> def func(self):
> pass
> Here, my_dec should return a method rathar than a function/lambda. Am I right?

Nope. Functions defined within a class statement are plain ordinary
functions. It's the lookup mechanism that "turns them into methods" when
they are looked up as attribute of a class. In fact, Python "methods"
are thin callable wrappers around a function, a class and (most of the
time) an instance, wrappers which are created - usually at lookup time -
by the __get__ method of the function type (you may want to read about
the descriptor protocol on python.org - in the section about new style
classes IIRC).

Anyway, you can explore this by yourself:

>>> Boo.far
<unbound method Boo.far>
>>> b.far
<bound method Boo.far of <__main__.Boo object at 0xb787f96c>>
>>> Boo.__dict__['far']
<function far at 0xb7c28aac>
>>> Boo.__dict__['far'] is far
True
>>> f1 = b.far
>>> f2 = b.far
>>> f1 is f2
False
>>> f1()
<__main__.Boo object at 0xb787f96c>
>>> f2()
<__main__.Boo object at 0xb787f96c>
>>> dir(f1)
['__call__', '__class__', '__cmp__', '__delattr__', '__doc__',
'__get__', '__getattribute__', '__hash__', '__init__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__',
'im_class', 'im_func', 'im_self']
>>> f1.im_class
<class '__main__.Boo'>
>>> f1.im_func
<function far at 0xb7c28aac>
>>> f1.im_func is far
True
>>> f1.im_self
<__main__.Boo object at 0xb787f96c>
>>> f1.im_self is b
True
>>> bf = Boo.far
>>> bf.im_func
<function far at 0xb7c28aac>
>>> bf.im_func is far
True
>>> bf.im_class
<class '__main__.Boo'>
>>> bf.im_self
>>> bf.im_self is None
True
>>> far.__get__(b, Boo)
<bound method Boo.far of <__main__.Boo object at 0xb787f96c>>
>>> far.__get__(b, Boo).im_func is far
True
>>>


So, to answer your question: what you are decorating are functions, not
methods.

> What does @property @staticmethod... really do? I cannot step-into them for
> source code.

staticmethod wraps the function into an object that, when looked up as
an attribute, will return the raw function instead of returning a method.

property is a type that provides a simple generic implementation for
computed attributes. You'll find more detailed explanations in the doc
(but perhaps not in the most obvious place - it's somewhere in the peps
or in the 'nws style classes' stuff IIRC). Anyway, using it as a
decorator is a somewhat special case (well... to me at least), that will
defined a property with only a getter (the decorated function).

> 4.
> If most of above questions can be solved, then it would be easy to implement
> the feature: "dynamic property attach".
> Eg:
> One class can read/store settings from/to some file based on
> the file content.
> # File: cfg.ini
> x = 1
> y = python
> config = SettingClass('cfg.ini') # dynamically build up properties x and y.
> x = config.x # x will be set to 1 (str -> int convertion would be
> done by 'property x')
> y = config.y # y will be set to 'python'
> config.x = 9 # 'x = 9' is written to cfg.ini.
>
> How to implement

In this case, I'd rather use the __getattr__/__setattr__ hooks. It won't
work with properties nor custom descriptors, since descriptors only work
as class attributes - not as instance attributes (which BTW is why
setting a function as an instance attribute doesn't make it a method...)


here are a couple links to relevant documentation and stuffs:
http://www.python.org/download/releases/2.2.3/d...
http://users.rcn.com/python/download/Desc...
http://www.python.org/doc...

> ^_^ Maybe there are some library does the same thing.

Indeed:
http://www.voidspace.org.uk/python/conf...
http://wiki.python.org/moin/ConfigPars...


HTH

Aaron Brady

3/4/2008 6:17:00 PM

0

On Mar 4, 5:27 am, Bruno Desthuilliers <bruno.
42.desthuilli...@wtf.websiteburo.oops.com> wrote:
> ?? a écrit :
>
> > Howdy everyone,
>
> >      This is a big problem puzzles me for a long time. The core question is:
> > How to dynamically create methods on a class or an instance?
>
> class Foo(object):
>     pass
>
> def bar(self, arg):
>     print "in bar : self == % - arg == %s" % (self, str(arg))
>
> def baaz(self, arg):
>     print "in baaz : self == % - arg == %s" % (self, str(arg))
>
> f = Foo()
>
> # adding bar as a method to class Foo
> Foo.bar = bar
>
> # f now can use bar:
> f.bar(42)
>
> # as well as new instances of Foo, of course
> g = Foo()
> g.bar()
>
> # adding baaz as a method to f, the old way:
> import new
> f.baaz = new.instancemethod(baaz, f, type(f))
>
> f.baaz()
>
> # adding baaz as a method to g, the other way:
> g.baaz = baaz.__get__(g, type(g))
>
> g.baaz()
>
> > Let me state it step by step.
> > 1.
> > def gunc(self):
> >     pass
> > class A(object):
> >     def func(self):
> >         pass
> > a = A()
> > a.func   # gives "bound method", type is "instancemethod"
> > A.func  # gives "unbound method", type is "instancemethod"
> > gunc    # gives "function", type if "function"
>
> > # ?? Does this line attach a method to instance?  ... I don't think so.
> > a.gunc = gunc
>
> It doesn't.
>
> > I found stardard library 'new' may help. Is that right?
>
> cf above. If you work with old-style classes, you'll need
> new.instancemethod.
>
> > 2.
> > a = A()  # instance of old class A
> > # Do attach a new method to class A...
> > b = A()  # instance of new class A
> > Does "a" can get the new method automatically?
>
> Yes. In Python, a class is itself an object, and is an attribute of it's
> instances (instance.__class__). Names are resolved at runtime, and
> attributes not found in the instance's __dict__ are looked up in the
> class (and then in the superclasses etc).
>
> > Does new method have the *same* concept level with old methods?
>
> The newly added method works exactly the same way as already existing
> ones. Not a single difference. The class statement is just syntactic
> sugar anyway. The following snippets are equivalent:
>
> # sugar-coated:
> class Boo(object):
>      faaz = 0
>
>      def far(self):
>          type(self).faaz += 1
>          print self
>
>      def frob(self):
>          print "yadda"
>
> # raw:
> def far(self):
>      type(self).faaz += 1
>      print self
>
> Boo = type('Boo', (object,), dict(faaz=0, far=far))
>
> def frob(self):
>     print "yadda"
>
> Boo.frob = frob
>
> > Especially, if there
> > are classes inherit from class A, how does name resolution work on this case?
>
> As usual.
>
> > 3.
> > How do I write a decroator for a method?
>
> Mostly the same way you'd write a decorator for a function
>
> > Eg:
> > class A(object):
> >     @my_dec
> >     def func(self):
> >         pass
> > Here, my_dec should return a method rathar than a function/lambda. Am I right?
>
> Nope. Functions defined within a class statement are plain ordinary
> functions. It's the lookup mechanism that "turns them into methods" when
> they are looked up as attribute of a class. In fact, Python "methods"
> are thin callable wrappers around a function, a class and (most of the
> time) an instance, wrappers which are created - usually at lookup time -
> by the __get__ method of the function type (you may want to read about
> the descriptor protocol on python.org - in the section about new style
> classes IIRC).
>
> Anyway, you can explore this by yourself:
>
>  >>> Boo.far
> <unbound method Boo.far>
>  >>> b.far
> <bound method Boo.far of <__main__.Boo object at 0xb787f96c>>
>  >>> Boo.__dict__['far']
> <function far at 0xb7c28aac>
>  >>> Boo.__dict__['far'] is far
> True
>  >>> f1 = b.far
>  >>> f2 = b.far
>  >>> f1 is f2
> False
>  >>> f1()
> <__main__.Boo object at 0xb787f96c>
>  >>> f2()
> <__main__.Boo object at 0xb787f96c>
>  >>> dir(f1)
> ['__call__', '__class__', '__cmp__', '__delattr__', '__doc__',
> '__get__', '__getattribute__', '__hash__', '__init__', '__new__',
> '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__',
> 'im_class', 'im_func', 'im_self']
>  >>> f1.im_class
> <class '__main__.Boo'>
>  >>> f1.im_func
> <function far at 0xb7c28aac>
>  >>> f1.im_func is far
> True
>  >>> f1.im_self
> <__main__.Boo object at 0xb787f96c>
>  >>> f1.im_self is b
> True
>  >>> bf = Boo.far
>  >>> bf.im_func
> <function far at 0xb7c28aac>
>  >>> bf.im_func is far
> True
>  >>> bf.im_class
> <class '__main__.Boo'>
>  >>> bf.im_self
>  >>> bf.im_self is None
> True
>  >>> far.__get__(b, Boo)
> <bound method Boo.far of <__main__.Boo object at 0xb787f96c>>
>  >>> far.__get__(b, Boo).im_func is far
> True
>  >>>
>
> So, to answer your question: what you are decorating are functions, not
> methods.

Can you overload -type-'s decision of what to 'bind'?... whenever it
is it makes it.

Aaron Brady

3/4/2008 6:46:00 PM

0

> > So, to answer your question: what you are decorating are functions, not
> > methods.
>
> Can you overload -type-'s decision of what to 'bind'?... whenever it
> is it makes it.

>>> from types import FunctionType, MethodType
>>> class A( FunctionType ): pass
....
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type 'function' is not an acceptable base type
>>> class A( MethodType ): pass
....
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type 'method' is not an acceptable base type

Unacceptable.

Gabriel Genellina

3/5/2008 2:12:00 AM

0

En Tue, 04 Mar 2008 16:45:40 -0200, <castironpi@gmail.com> escribió:

>> > So, to answer your question: what you are decorating are functions,
>> not
>> > methods.
>>
>> Can you overload -type-'s decision of what to 'bind'?... whenever it
>> is it makes it.
>
>>>> from types import FunctionType, MethodType
>>>> class A( FunctionType ): pass
> ...
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> TypeError: type 'function' is not an acceptable base type

Use delegation instead of inheritance. This class is almost
indistinguishable from a true function (when used as a method):

py> class myfunction(object):
.... __slots__ = ('func',)
.... #
.... def __init__(self, func):
.... object.__setattr__(self, 'func', func)
.... #
.... def __get__(self, instance, owner):
.... print "__get__ called for",instance
.... return self.func.__get__(instance, owner)
.... #
.... def __getattr__(self, name):
.... return getattr(self.func, name)
.... #
.... def __setattr__(self, name, value):
.... object.__setattr__(self.func, name, value)
....
py>
py> class P(object):
.... def foo(self, x): print 'foo',x
.... #
.... @myfunction
.... def bar(self, x): print 'bar',x
....
py> p = P()
py> p.foo(1)
foo 1
py> p.bar(2)
__get__ called for <__main__.P object at 0x00A3D650>
bar 2
py> P.foo(p, 1)
foo 1
py> P.bar(p, 2)
__get__ called for None
bar 2
py> print "p.foo", p.foo, type(p.foo)
p.foo <bound method P.foo of <__main__.P object at 0x00A3D650>> <type
'instancem
ethod'>
py> print "p.bar", p.bar, type(p.bar)
p.bar __get__ called for <__main__.P object at 0x00A3D650>
<bound method P.bar of <__main__.P object at 0x00A3D650>> __get__ called
for <__
main__.P object at 0x00A3D650>
<type 'instancemethod'>
py> print set(dir(p.foo))==set(dir(p.bar))
__get__ called for <__main__.P object at 0x00A3D650>
True
py> print "P.foo", P.foo, type(P.foo)
P.foo <unbound method P.foo> <type 'instancemethod'>
py> print "P.bar", P.bar, type(P.bar)
P.bar __get__ called for None
<unbound method P.bar> __get__ called for None
<type 'instancemethod'>
py> print set(dir(P.foo))==set(dir(P.bar))
__get__ called for None
True
py> P.__dict__['foo']
<function foo at 0x00A3BCB0>
py> P.__dict__['bar']
<__main__.myfunction object at 0x00A3D690>


Ok, let's try returning a different thing from __get__: bound method ->
partial with self already bound; unbound method -> the original function.

py> from functools import partial
py>
py> class myfunction2(myfunction):
.... def __get__(self, instance, owner):
.... if instance is None:
.... return self.func
.... return partial(self.func, instance)
....
py> @myfunction2
.... def baz(self, x): print 'baz',x
....
py> P.baz = baz
py> print p.baz
<functools.partial object at 0x00A3E5A0>
py> print P.baz
<function baz at 0x00AB1030>
py> p.baz(3)
baz 3
py> P.baz(p,3)
baz 3

--
Gabriel Genellina

Aaron Brady

3/5/2008 2:30:00 AM

0

On Mar 4, 8:11 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.ar> wrote:
> En Tue, 04 Mar 2008 16:45:40 -0200, <castiro...@gmail.com> escribió:
>
> >> > So, to answer your question: what you are decorating are functions,  
> >> not
> >> > methods.
>
> >> Can you overload -type-'s decision of what to 'bind'?... whenever it
> >> is it makes it.
>
> >>>> from types import FunctionType, MethodType
> >>>> class A( FunctionType ): pass
> > ...
> > Traceback (most recent call last):
> >   File "<stdin>", line 1, in <module>
> > TypeError: type 'function' is not an acceptable base type
>
> Use delegation instead of inheritance. This class is almost  
> indistinguishable from a true function (when used as a method):
>
> py> class myfunction(object):
> ...   __slots__ = ('func',)
> ...   #
> ...   def __init__(self, func):
> ...     object.__setattr__(self, 'func', func)
> ...   #
> ...   def __get__(self, instance, owner):
> ...     print "__get__ called for",instance
> ...     return self.func.__get__(instance, owner)
> ...   #
> ...   def __getattr__(self, name):
> ...     return getattr(self.func, name)
> ...   #
> ...   def __setattr__(self, name, value):
> ...     object.__setattr__(self.func, name, value)
> ...
> py>
> py> class P(object):
> ...   def foo(self, x): print 'foo',x
> ...   #
> ...   @myfunction
> ...   def bar(self, x): print 'bar',x
> ...
> py> p = P()
> py> p.foo(1)
> foo 1
> py> p.bar(2)
> __get__ called for <__main__.P object at 0x00A3D650>
> bar 2
> py> P.foo(p, 1)
> foo 1
> py> P.bar(p, 2)
> __get__ called for None
> bar 2
> py> print "p.foo", p.foo, type(p.foo)
> p.foo <bound method P.foo of <__main__.P object at 0x00A3D650>> <type  
> 'instancem
> ethod'>
> py> print "p.bar", p.bar, type(p.bar)
> p.bar __get__ called for <__main__.P object at 0x00A3D650>
> <bound method P.bar of <__main__.P object at 0x00A3D650>> __get__ called  
> for <__
> main__.P object at 0x00A3D650>
> <type 'instancemethod'>
> py> print set(dir(p.foo))==set(dir(p.bar))
> __get__ called for <__main__.P object at 0x00A3D650>
> True
> py> print "P.foo", P.foo, type(P.foo)
> P.foo <unbound method P.foo> <type 'instancemethod'>
> py> print "P.bar", P.bar, type(P.bar)
> P.bar __get__ called for None
> <unbound method P.bar> __get__ called for None
> <type 'instancemethod'>
> py> print set(dir(P.foo))==set(dir(P.bar))
> __get__ called for None
> True
> py> P.__dict__['foo']
> <function foo at 0x00A3BCB0>
> py> P.__dict__['bar']
> <__main__.myfunction object at 0x00A3D690>
>
> Ok, let's try returning a different thing from __get__: bound method ->  
> partial with self already bound; unbound method -> the original function.
>
> py> from functools import partial
> py>
> py> class myfunction2(myfunction):
> ...   def __get__(self, instance, owner):
> ...     if instance is None:
> ...         return self.func
> ...     return partial(self.func, instance)
> ...
> py> @myfunction2
> ... def baz(self, x): print 'baz',x
> ...
> py> P.baz = baz
> py> print p.baz
> <functools.partial object at 0x00A3E5A0>
> py> print P.baz
> <function baz at 0x00AB1030>
> py> p.baz(3)
> baz 3
> py> P.baz(p,3)
> baz 3
>
> --
> Gabriel Genellina

I actually don't believe you-- bar is not bound to an instance when P
is initialized... er, instantiated. However, the evidence indicates
my belief mechanism is faulty... and rather conclusively at that.
<moves to acquire new evidence> If P calls __get__( you ), is p a
gotcha?

Gabriel Genellina

3/5/2008 3:02:00 AM

0

En Wed, 05 Mar 2008 00:30:26 -0200, <castironpi@gmail.com> escribió:
> On Mar 4, 8:11 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.ar> wrote:
>> En Tue, 04 Mar 2008 16:45:40 -0200, <castiro...@gmail.com> escribió:
>>
>> >> Can you overload -type-'s decision of what to 'bind'?... whenever it
>> >> is it makes it.
>>
>> >>>> from types import FunctionType, MethodType
>> >>>> class A( FunctionType ): pass
>> > ...
>> > Traceback (most recent call last):
>> >   File "<stdin>", line 1, in <module>
>> > TypeError: type 'function' is not an acceptable base type
>>
>> Use delegation instead of inheritance. This class is almost  
>> indistinguishable from a true function (when used as a method):

[... long interactive example ...]

> I actually don't believe you-- bar is not bound to an instance when P
> is initialized... er, instantiated. However, the evidence indicates
> my belief mechanism is faulty... and rather conclusively at that.
> <moves to acquire new evidence> If P calls __get__( you ), is p a
> gotcha?

I didn't cheat, that was an actual Python interactive session. So you'll
have to formulate a new theory taking into account the new facts... or
read how the descriptor protocol works http://www.python.org/doc...
I don't understand your last sentence.

--
Gabriel Genellina

Aaron Brady

3/5/2008 3:54:00 AM

0

On Mar 4, 9:01 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.ar> wrote:
> En Wed, 05 Mar 2008 00:30:26 -0200, <castiro...@gmail.com> escribió:
>
> > On Mar 4, 8:11 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.ar> wrote:
> >> En Tue, 04 Mar 2008 16:45:40 -0200, <castiro...@gmail.com> escribió:
>
> >> >> Can you overload -type-'s decision of what to 'bind'?... whenever it
> >> >> is it makes it.
>
> >> >>>> from types import FunctionType, MethodType
> >> >>>> class A( FunctionType ): pass
> >> > ...
> >> > Traceback (most recent call last):
> >> >   File "<stdin>", line 1, in <module>
> >> > TypeError: type 'function' is not an acceptable base type
>
> >> Use delegation instead of inheritance. This class is almost  
> >> indistinguishable from a true function (when used as a method):
>
> [... long interactive example ...]
>
> > I actually don't believe you-- bar is not bound to an instance when P
> > is initialized... er, instantiated.  However, the evidence indicates
> > my belief mechanism is faulty... and rather conclusively at that.
> > <moves to acquire new evidence>  If P calls __get__( you ), is p a
> > gotcha?
>
> I didn't cheat, that was an actual Python interactive session. So you'll  
> have to formulate a new theory taking into account the new facts... or  
> read how the descriptor protocol workshttp://www.python.org/doc...
> I don't understand your last sentence.
>
> --
> Gabriel Genellina

<joke>
If P gets, p gotcha.
</joke>

gotcha= partial( get, you ). bor hor hor. Yes... regarding the
descriptoring, just make it official! UserFunctionType or smg.

Aaron Brady

3/5/2008 4:03:00 AM

0

On Mar 4, 9:53 pm, castiro...@gmail.com wrote:
> > >> >> Can you overload -type-'s decision of what to 'bind'?... whenever it
> > >> >> is it makes it.
>
> > >> >>>> from types import FunctionType, MethodType
> > >> >>>> class A( FunctionType ): pass
> > >> > ...
> > >> > Traceback (most recent call last):
> > >> >   File "<stdin>", line 1, in <module>
> > >> > TypeError: type 'function' is not an acceptable base type
>
> > >> Use delegation instead of inheritance. This class is almost  
> > >> indistinguishable from a true function (when used as a method):
> If P gets, p gotcha.
> </joke>
>
> gotcha= partial( get, you ).  bor hor hor.  Yes...

Notwithstanding. Now bar has a name.

class myfunction:
__slots__ = ('func','name')
#
def __init__(self, func):
object.__setattr__(self, 'func', func)
object.__setattr__(self, 'name', None)
#
def __get__(self, instance, owner):
print( "__get__ called for",instance )
return self.func.__get__(instance, owner)
#
def __getattr__(self, name):
return getattr(self.func, name)
#
def __setattr__(self, name, value):
object.__setattr__(self.func, name, value)

class mymeta( type ):
def __init__( self, name, bases, namespace ):
for k,v in namespace.items():
if isinstance( v, myfunction ):
v.name= k

class P( metaclass= mymeta ):
def foo(self, x): print( 'foo',x )
#
@myfunction
def bar(self, x): print( 'bar',x )

p= P()
p.foo( 0 )
p.bar( 1 )
print( p.bar )
print( p.bar.name )

'''
output:
'''
foo 0
__get__ called for <__main__.P object at 0x00B481F0>
bar 1
__get__ called for <__main__.P object at 0x00B481F0>
<bound method P.bar of <__main__.P object at 0x00B481F0>>
__get__ called for <__main__.P object at 0x00B481F0>
bar

Aaron Brady

3/5/2008 4:58:00 AM

0

> > > >> >> Can you overload -type-'s decision of what to 'bind'?... whenever it
> > > >> >> is it makes it.
>
> > > >> >>>> from types import FunctionType, MethodType
> > > >> >>>> class A( FunctionType ): pass
> > > >> > ...
> > > >> > Traceback (most recent call last):
> > > >> >   File "<stdin>", line 1, in <module>
> > > >> > TypeError: type 'function' is not an acceptable base type
>
> > > >> Use delegation instead of inheritance. This class is almost  
> > > >> indistinguishable from a true function (when used as a method):
> > If P gets, p gotcha.
> > </joke>
>
> > gotcha= partial( get, you ).  bor hor hor.  Yes...
>
> Notwithstanding.  Now bar has a name.

Now func has it.

from functools import wraps
class myfunction:
__slots__ = ('func','name')
#
def __init__(self, func):
@wraps( func )
def f( *ar, **kws ):
return func( self, *ar, **kws )
object.__setattr__(self, 'func', f)
object.__setattr__(self, 'name', None)
#
def __get__(self, instance, owner):
print( "__get__ called for",instance )
return self.func.__get__(instance, owner)
#
def __getattr__(self, name):
return getattr(self.func, name)
#
def __setattr__(self, name, value):
object.__setattr__(self.func, name, value)

class mymeta( type ):
def __init__( self, name, bases, namespace ):
for k,v in namespace.items():
if isinstance( v, myfunction ):
v.name= k

class P( metaclass= mymeta ):
def foo(self, x): print( 'foo',x )
#
@myfunction
def bar( fob,self, x): print( 'bar',fob,x )

p= P()
p.foo( 0 )
p.bar( 1 )
print( p.bar )
print( p.bar.name )