473,581 Members | 2,789 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Function creation (what happened?)

Can somebody give me an explanation what happened here (or point me to
some docs)?

Code:

HMMM = None

def w(fn):
print 'fn:', id(fn)
HMMM = fn
print 'HMMM:', id(HMMM)
def wrapper(*v, **kw):
fn(*v, **kw)
wrapper.i = fn
print 'wrapper:', id(wrapper)
return wrapper

class A:
@w
def __init__(self): pass

print 'A.__init__:', id(A.__init__)
print 'A.__init__.i:' , id(A.__init__.i )
print 'HMMM:', id(HMMM)

Output:

fn: 10404208
HMMM: 10404208
wrapper: 10404272
A.__init__: 10376136
A.__init__.i: 10404208
HMMM: 505264624

Why did HMMM changed his id?!
Jun 27 '08 #1
8 1523
On May 9, 8:25 am, Viktor <alefn...@gmail .comwrote:
Can somebody give me an explanation what happened here (or point me to
some docs)?

Code:

HMMM = None

def w(fn):
print 'fn:', id(fn)
HMMM = fn
print 'HMMM:', id(HMMM)
def wrapper(*v, **kw):
fn(*v, **kw)
wrapper.i = fn
print 'wrapper:', id(wrapper)
return wrapper

class A:
@w
def __init__(self): pass

print 'A.__init__:', id(A.__init__)
print 'A.__init__.i:' , id(A.__init__.i )
print 'HMMM:', id(HMMM)

Output:

fn: 10404208
HMMM: 10404208
wrapper: 10404272
A.__init__: 10376136
A.__init__.i: 10404208
HMMM: 505264624

Why did HMMM changed his id?!
The HMMM inside w is local to that function and is not the same HMMM
that is defined just before w.
Have a look at http://docs.python.org/ref/global.html

cheers
Jun 27 '08 #2
Viktor <al******@gmail .comwrote:
Can somebody give me an explanation what happened here (or point me to
some docs)?

Code:

HMMM = None

def w(fn):
print 'fn:', id(fn)
HMMM = fn
print 'HMMM:', id(HMMM)
def wrapper(*v, **kw):
fn(*v, **kw)
wrapper.i = fn
print 'wrapper:', id(wrapper)
return wrapper

class A:
@w
def __init__(self): pass

print 'A.__init__:', id(A.__init__)
print 'A.__init__.i:' , id(A.__init__.i )
print 'HMMM:', id(HMMM)

Output:

fn: 10404208
HMMM: 10404208
wrapper: 10404272
A.__init__: 10376136
A.__init__.i: 10404208
HMMM: 505264624

Why did HMMM changed his id?!
It didn't: global HMMM refers to None both before and after executing
the rest of your code. The other HMMM is local to a particular
invocation of w. Try the same steps interactively (and try printing the
values not just the ids) and it may be more obvious:
>>HMMM = None
print 'HMMM:', id(HMMM)
HMMM: 505264624
>>def w(fn):
print 'fn:', id(fn)
HMMM = fn
print 'HMMM:', id(HMMM)
def wrapper(*v, **kw):
fn(*v, **kw)
wrapper.i = fn
print 'wrapper:', id(wrapper)
return wrapper
>>class A:
@w
def __init__(self): pass
fn: 18299952
HMMM: 18299952
wrapper: 18300016
>>print 'HMMM:', id(HMMM), HMMM
HMMM: 505264624 None
>>>
Jun 27 '08 #3
Viktor wrote:
Can somebody give me an explanation what happened here (or point me to
some docs)?

Code:

HMMM = None

def w(fn):
print 'fn:', id(fn)
HMMM = fn
print 'HMMM:', id(HMMM)
This prints the id() of the local (to the function w()) HMMM variable
def wrapper(*v, **kw):
fn(*v, **kw)
wrapper.i = fn
print 'wrapper:', id(wrapper)
return wrapper

class A:
@w
def __init__(self): pass

print 'A.__init__:', id(A.__init__)
print 'A.__init__.i:' , id(A.__init__.i )
print 'HMMM:', id(HMMM)
while this prints the id() of the global HMMM variable. Python assumes that
a variable is local to a function if there is an assignment to that
variable anywhere inside that function.

If you want to change the variable (Python-lingo "rebind the name") HMMM
declare it as global in the function:

def w(fn):
global HMMM
# ...
HMMM = fn
# ...

Otherwise I've no idea what you are trying to do here...

Peter
Jun 27 '08 #4
This completely slipped of my mind... :)

I'm trying to change the:
http://wordaligned.org/svn/etc/echo/echo.py

So if the function is method it prints ClassName.Metho dName instead of
MethodName(self |klass|cls=<... ClassName>).

But it turned out that in the decorator, the wrapped function is
always just a TypeFunction (I cannot find out if the function is
method, classmethod, staticmethod or just a plain function - tried
with inspect also)... And what is most interesting, when I do:

def w(fn):
print 'fn:', id(fn)
return fn

class A:
@w
def __init__(self): pass

print 'A.__init__:', id(A.__init__)

It turns out that the function I receive in the wrapper (even when I
return the same function) is not the function which will finally be
attached to the class...

Is there a way to find out in the decorator "what will the decorated
function be"?
Jun 27 '08 #5
On May 9, 9:02*am, Viktor <alefn...@gmail .comwrote:
This completely slipped of my mind... :)

I'm trying to change the:http://wordaligned.org/svn/etc/echo/echo.py

So if the function is method it prints ClassName.Metho dName instead of
MethodName(self |klass|cls=<... ClassName>).

But it turned out that in the decorator, the wrapped function is
always just a TypeFunction (I cannot find out if the function is
method, classmethod, staticmethod or just a plain function - tried
with inspect also)... And what is most interesting, when I do:

def w(fn):
* * print 'fn:', id(fn)
* * return fn

class A:
* * @w
* * def __init__(self): pass

print 'A.__init__:', id(A.__init__)

It turns out that the function I receive in the wrapper (even when I
return the same function) is not the function which will finally be
attached to the class...

Is there a way to find out in the decorator "what will the decorated
function be"?
The decorator does receive the correct function. The problem is that
at this point __init__ is still a plain function, not a method, i.e.
the sequence is:
function -decorated function -method

There are several workarounds if you really want to differentiate
between functions and methods, none of them perfect:

- Apply the decorator after the class has been built, i.e. after the
functions have been wrapped in (unbound) methods:
A.__init__ = w(A.__init__)

- (Risky Hack): Guess whether a function is intended to be wrapped in
a method by checking whether its first argument is named "self".
Obviously this is not foolproof and it doesn't work for static/class
methods.

- Have two different decorators, one intended for plain functions and
one for functions-to-be-methods (e.g. @deco, @decomethod).

George
Jun 27 '08 #6
I figured out the first two solutions, but the third looks like the
most cleaner, think I'll use that one...

Thank you everyone. :)

On May 9, 3:24 pm, George Sakkis <george.sak...@ gmail.comwrote:
The decorator does receive the correct function. The problem is that
at this point __init__ is still a plain function, not a method, i.e.
the sequence is:
function -decorated function -method

There are several workarounds if you really want to differentiate
between functions and methods, none of them perfect:

- Apply the decorator after the class has been built, i.e. after the
functions have been wrapped in (unbound) methods:
A.__init__ = w(A.__init__)

- (Risky Hack): Guess whether a function is intended to be wrapped in
a method by checking whether its first argument is named "self".
Obviously this is not foolproof and it doesn't work for static/class
methods.

- Have two different decorators, one intended for plain functions and
one for functions-to-be-methods (e.g. @deco, @decomethod).

George
Jun 27 '08 #7
En Fri, 09 May 2008 10:02:01 -0300, Viktor <al******@gmail .comescribió:
This completely slipped of my mind... :)

I'm trying to change the:
http://wordaligned.org/svn/etc/echo/echo.py

So if the function is method it prints ClassName.Metho dName instead of
MethodName(self |klass|cls=<... ClassName>).

But it turned out that in the decorator, the wrapped function is
always just a TypeFunction (I cannot find out if the function is
method, classmethod, staticmethod or just a plain function - tried
with inspect also)... And what is most interesting, when I do:
The decorator receives the original, plain function (unless you chain decorators) and whatever it returns is used instead of the original function.
def w(fn):
print 'fn:', id(fn)
return fn

class A:
@w
def __init__(self): pass

print 'A.__init__:', id(A.__init__)

It turns out that the function I receive in the wrapper (even when I
return the same function) is not the function which will finally be
attached to the class...
Is there a way to find out in the decorator "what will the decorated
function be"?
Whatever you return from the decorator.
But the decorator returns a *function* and A.__init__ is a *method*, an instance method in fact. The function can be found as A.__dict__['__init__']. Try this:

m = A.__init__
print m, type(m), id(m)
f = A.__dict__['__init__']
print f, type(f), id(f)

A method combines a function with an instance that becomes the "self" argument. In your case you're building an "unbound" method because it's not tied to a particular instance, but even such unbound method is not the same thing as a plain function (it must ensure that its first argument, when called, is an A instance and not any other object).
The "magic" that converts a simple function into an instance method, for old-style classes like yours, was in the Class type itself. For new style classes, the descriptor protocol is used. See http://www.python.org/doc/newstyle/

--
Gabriel Genellina

Jun 27 '08 #8
Viktor a écrit :
This completely slipped of my mind... :)

I'm trying to change the:
http://wordaligned.org/svn/etc/echo/echo.py

So if the function is method it prints ClassName.Metho dName instead of
MethodName(self |klass|cls=<... ClassName>).

But it turned out that in the decorator, the wrapped function is
always just a TypeFunction
s/TypeFunction/function/
(I cannot find out if the function is
method, classmethod, staticmethod or just a plain function
The latter, unless you decorate it with a classmethod or staticmethod
object before.
- tried
with inspect also)... And what is most interesting, when I do:

def w(fn):
print 'fn:', id(fn)
return fn

class A:
@w
def __init__(self): pass

print 'A.__init__:', id(A.__init__)

It turns out that the function I receive in the wrapper (even when I
return the same function) is not the function which will finally be
attached to the class...
Yes it is. But A.__init__ is *not* a function, it's a method. To get at
the function, you must use A.__dict__['__init__'] or A.__init__.im_f unc
Is there a way to find out in the decorator "what will the decorated
function be"?
Yes : the decorated function is the function you decorate with the
decorator.

Ok, this requires some explanations (nb: only valid for new-style classes):

- First point : what you declare in the class statement are plain
ordinary function. When the class statement is executed - that is,
usually[1], at import time - these function objects become attributes of
the class object.
[1] IOW : if your class statement is at the top-level of your module

- Second point: the function class implements the descriptor
protocol[2], so when an attribute lookup resolves to a function object,
the function's class __get__ method is invoked
[2] http://users.rcn.com/python/download/Descriptor.htm

- Third point: the function's __get__ method returns a method object,
either bound (if lookup was done on an instance) or unbound (if the
lookup was done on a class).

The function's class __get__ method could be implemented this way:

def __get__(self, instance, cls):
return types.MethodTyp e(self, instance, cls)
- Fourth point: a method object is a thin callable wrapper around the
function, the instance (if provided), and the class. It could look like
this:

class Method(object):
def __init__(self, func, instance, cls):
self.im_func = func
self.im_self = instance
self.im_class = cls

def __repr__(self):
if self.im_self is None:
# unbound
return "<unbound method %s.%s>" \
% (self.im_class. __name__, self.im_func.__ name__)
else:
# bound
return "<bound method %s.%s of %s>" \
% (self.im_class. __name__,
self.im_func.__ name__,
self.im_self)

def __call__(self, *args, **kw):
if self.im_self is None:
try:
instance, args = args[0], args[1:]
except IndexError:
raise TypeError(
"unbound method %s() must be called with %s instance "
" as first argument (got nothing instead)" \
% (self.im_func._ _name__, self.im_class._ _name__)
if not isinstance(inst ance, self.im_class):
raise TypeError(
"unbound method %s() must be called with %s instance "
" as first argument (got %s instead)" \
% (self.im_func._ _name__, self.im_class._ _name__, instance)

else:
instance = self.im_self
return self.im_func(in stance, *args, **kw)

The classmethod and staticmethod classes (yes, they are classes...) have
their own implementation for the descriptor protocol -
classmethod.__g et__ returns a Method instanciated with func, cls,
type(cls), and staticmethod.__ get__ returns the original function.
So as you can see - and classmethods and staticmethods set aside -, what
you decorate is *always* a function. And you just can't tell from within
the decorator if this function is called "directly" or from a method
object. The only robust solution is to decorate the function with your
own custom callable descriptor. Here's a Q&D untested example that
should get you started (warning : you'll have to check for classmethods
and staticmethods)

class wmethod(object) :
def __init__(self, method):
self.method = method

def __call__(self, *args, **kw):
# called as a method
# your tracing code here
# NB : you can access the method's
# func, class and instance thru
# self.method.im_ *,
return self.method(*ar gs, **kw)

class w(object):
def __init__(self, func):
self.func = func

def __get__(self, instance, cls):
return wmethod(self.fu nc.__get__(inst ance, cls))

def __call__(self, *args, **kw):
# called as a plain function
# your tracing code here
return self.func(*args , **kw)
HTH
Jun 27 '08 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

58
10091
by: jr | last post by:
Sorry for this very dumb question, but I've clearly got a long way to go! Can someone please help me pass an array into a function. Here's a starting point. void TheMainFunc() { // Body of code... TCHAR myArray; DoStuff(myArray);
4
3612
by: anonymous | last post by:
Thanks your reply. The article I read is from www.hakin9.org/en/attachments/stackoverflow_en.pdf. And you're right. I don't know it very clearly. And that's why I want to understand it; for it's useful to help me to solve some basic problem which I may not perceive before. I appreciate your help, sincerely.
2
1718
by: DFS | last post by:
The .mde creation just sits there, until I click on the blank screen and I get a (Not Responding) message in the title bar. The code compiles fine. Other systems of a similar large size compile and ..mde create fine, so I think it's not Access but something in this .mdb. Any ideas? Thanks
8
2225
by: vasudevram | last post by:
Hi, Is there any C library (free software or open source) for PDF creation, other than PDFLib? I'm looking for such a library to use for: 1. Porting my xtopdf PDF creation/conversion toolkit - see http://www.dancingbison.com/services.html - from Python to C, for reasons of a) possibly better performance, b) being able to wrap the
4
2699
by: Ray | last post by:
Hello, I think I've had JavaScript variable scope figured out, can you please see if I've got it correctly? * Variables can be local or global * When a variable is declared outside any function, it is global regardless of whether it's declared with or without "var" * When it is declared inside a function, if declared with "var", it's...
4
2111
by: alex | last post by:
I am so confused with these three concept,who can explained it?thanks so much? e.g. var f= new Function("x", "y", "return x * y"); function f(x,y){ return x*y } var f=function(x,y){
1
2222
by: Ricardo | last post by:
Hello, I have just happened on a nice Borland C++ 5.5 tutorial at http://www.webnotes.org/bcc55eng.htm, meant for the very novice like myself :) I got stuck at creation of .res file needed to include some resoureces into the EXE, e.g. an application icon. According to the author's description I prepared a file "testres.rc" with the following...
2
1521
by: Steven W. Orr | last post by:
I have some functions I need to create at runtime. The way I'm creating them is by calling a function which returns the string representation. Then I exec the string. Here's the code I use to gen the strings: mkfactfns.py ----------- import new def mkfactfns( cname ): def auxgen( name, params, dd ):
1
1493
by: Steven W. Orr | last post by:
I have this which works: #! /usr/bin/python strfunc = """ def foo( a ): print 'a = ', a """ exec strfunc globals() = foo foo( 'Hello' )
0
7882
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7808
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
8181
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6564
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
5366
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3809
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3835
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2309
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
0
1145
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.