473,602 Members | 2,887 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 1524
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
10097
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
3613
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
2700
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 local, if not, it's global
4
2112
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
2223
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 content: //==cut MAINICON ICON LOADONCALL MOVEABLE DISCARDABLE testres.ico //==cut where...
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
7993
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 usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
7921
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 synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8404
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8056
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
5870
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5440
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 into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
3944
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2424
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
1256
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 effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.