473,721 Members | 2,089 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 1532
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
10160
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
3622
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
1723
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
2227
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
2717
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
2134
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
2232
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
1524
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
1499
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
8853
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
9373
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
9146
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,...
0
9085
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 choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8025
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 launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6677
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
4498
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 the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4762
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
2145
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.