473,804 Members | 3,720 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

keeping a ref to a non-member function in a class

I'm building a class hierarchy that needs to keep as a class variable a
reference to a (non-member) function, so that different subclasses can
use different generator functions. But it seems Python is treating the
function as a member function because the reference to it is in class
scope....

Here's a simple case of what I'm trying (in the real code, fn is a
function that returns a database connection relevant to that subclass):
def foo():
print "foo called"

class S(object):
fn = foo

def bar(cls):
cls.fn()
bar = classmethod(bar )

def foo2():
print "foo2 called"

class D(S):
fn = foo2

D.bar()
[I'm on python 2.3.4 so no @classmethod decorator! ]

When I run this:
Traceback (most recent call last):
File "t_o.py", line 19, in ?
D.bar()
File "t_o.py", line 10, in bar
cls.fn()
TypeError: unbound method foo2() must be called with D instance as first argument (got nothing instead)


This shows it is trying to do what I expect (call foo2()) but somehow
the type is all wrong.

I've tried playing with staticmethod() but I can't quite get it all
worked out...
Aug 16 '05 #1
3 1714
Gregory Bond wrote:
I'm building a class hierarchy that needs to keep as a class variable a
reference to a (non-member) function, so that different subclasses can
use different generator functions. But it seems Python is treating the
function as a member function because the reference to it is in class
scope....

Here's a simple case of what I'm trying (in the real code, fn is a
function that returns a database connection relevant to that subclass):
def foo():
print "foo called"

class S(object):
fn = foo

def bar(cls):
cls.fn()
bar = classmethod(bar )

def foo2():
print "foo2 called"

class D(S):
fn = foo2

D.bar()
I've tried playing with staticmethod() but I can't quite get it all
worked out...


You are on the right track with staticmethod, but you have to apply it to
fn:
def foo(): print "first foo" .... def foo2(): print "second foo" .... class S(object): .... fn = staticmethod(fo o)
.... def bar(cls):
.... cls.fn()
.... bar = classmethod(bar )
.... class D(S): .... fn = staticmethod(fo o2)
.... S.bar() first foo D.bar() second foo

In its current form, the bar() method is not necessary:
S.fn() first foo D.fn()

second foo

Peter

Aug 16 '05 #2
Peter Otten wrote:

You are on the right track with staticmethod, but you have to apply it to
fn:

... fn = staticmethod(fo o)

Thanks Peter, that's a big help.

I can solve my problem now, but I'm chasing this further in the name of
education, because it seems there is some deep magic happening here that
I don't understand.

It seems that applying staticfunction( ) (or perhaps assigning to the
class object) is treated differently if it happens in the class
defininition, to when it happens at "run time". (My previous attempts
to get staticmember() to do the right thing were all "run time" like the
examples below.)

Say I wanted to keep the need for "staticmemb er" hidden from subclasses,
and do the staticmember() conversion in the base class methods. I've
tried 2 ways of doing this (no subclassing here, just to keep it simple):
class B(object):
fn = foo
def try1(self):
print "B.fn is", type(B.fn)
B.fn = staticmethod(B. fn)
print "B try1"
print "B.fn is now", type(B.fn)
B.fn()

def try2(self):
fn2 = staticmethod(B. fn)
print "B try2"
print "fn2 is now", type(fn2)
fn2()
If I try method 1 (assigning to the class object - ignore for a moment
the problem of only doing this once!) I get a set of very surprising
results:
B.fn is <type 'instancemethod '>
B try1
B.fn is now <type 'instancemethod '>
Traceback (most recent call last):
File "t_o1.py", line 28, in ?
B().try1()
File "t_o1.py", line 17, in try1
B.fn()
TypeError: unbound method foo() must be called with B instance as first argument (got nothing instead)
note that assigning the staticmember() result to B.fn does NOT change
the type of B.fn!! And foo is treated as a member function.

So if I try method 2 (using staticmethod() at runtime):
B try2
fn2 is now <type 'staticmethod'>
Traceback (most recent call last):
File "t_o1.py", line 27, in ?
B().try2()
File "t_o1.py", line 22, in try2
fn2()
TypeError: 'staticmethod' object is not callable


fn2 is a static method, as I'd expect, but it is somehow not callable?

Can someone explain what is going on here? Pointers to language spec,
code, PEPs etc gladly accepted.

Greg,
caught in a twisty little maze of descriptors, all different!
Aug 17 '05 #3
Gregory Bond wrote:
Thanks Peter, that's a big help.
You're welcome.
I can solve my problem now, but I'm chasing this further in the name of
education, because it seems there is some deep magic happening here that
I don't understand.
Python resorts to deep magic only when it's inevitable, i. e. hardly
ever :-)
It seems that applying staticfunction( ) (or perhaps assigning to the
class object) is treated differently if it happens in the class
defininition, to when it happens at "run time". (My previous attempts
to get staticmember() to do the right thing were all "run time" like the
examples below.)
There is no distinction between "run time" and "class definition time". The
class "body" is actually a function that is called when the module is
loaded. Its locals() are then used to create a type instance, i. e. the
class.
Say I wanted to keep the need for "staticmemb er" hidden from subclasses,
and do the staticmember() conversion in the base class methods. I've
tried 2 ways of doing this (no subclassing here, just to keep it simple):
class B(object):
fn = foo
def try1(self):
print "B.fn is", type(B.fn)
B.fn = staticmethod(B. fn)
print "B try1"
print "B.fn is now", type(B.fn)
B.fn()

def try2(self):
fn2 = staticmethod(B. fn)
print "B try2"
print "fn2 is now", type(fn2)
fn2()
If I try method 1 (assigning to the class object - ignore for a moment
the problem of only doing this once!) I get a set of very surprising
results:
B.fn is <type 'instancemethod '>
B try1
B.fn is now <type 'instancemethod '>
Traceback (most recent call last):
File "t_o1.py", line 28, in ?
B().try1()
File "t_o1.py", line 17, in try1
B.fn()
TypeError: unbound method foo() must be called with B instance as first
argument (got nothing instead)


note that assigning the staticmember() result to B.fn does NOT change
the type of B.fn!! And foo is treated as a member function.

So if I try method 2 (using staticmethod() at runtime):
B try2
fn2 is now <type 'staticmethod'>
Traceback (most recent call last):
File "t_o1.py", line 27, in ?
B().try2()
File "t_o1.py", line 22, in try2
fn2()
TypeError: 'staticmethod' object is not callable


fn2 is a static method, as I'd expect, but it is somehow not callable?


Your problems stem from the fact that attribute assignment to a class
doesn't always roundtrip:
A.value = 42
A.value 42 def f(): pass .... A.method = f
A.method, f (<unbound method A.f>, <function f at 0x4028eae4>)

If a class attribute is a descriptor i. e. it has a __get__() method (which
pure python functions do) A.method is not just a dictionary lookup but a
call

A.__dict__["method"].__get__(None, A)

This is slightly simplified as it doesn't take inheritance into account.
__get__() is free to apply whatever magic, but staticmethod just gives back
the original function whereas a some_func.__get __(None, SomeClass) gives
you an unbound method:
staticmethod(f) .__get__(None, A) <function f at 0x4028eae4> f.__get__(None, A) <unbound method A.f>

Is there a way to get the original function back out of the unbound method?
Let's see:
dir(A.method) ['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__get__',
'__getattribute __', '__hash__', '__init__', '__new__', '__reduce__',
'__reduce_ex__' , '__repr__', '__setattr__', '__str__', 'im_class',
'im_func', 'im_self']

im_func seems promising:
A.method.im_fun c

<function f at 0x4028eae4>
Can someone explain what is going on here? Pointers to language spec,
code, PEPs etc gladly accepted.

Greg,
caught in a twisty little maze of descriptors, all different!


The two relevant documents are

http://users.rcn.com/python/download/Descriptor.htm
http://www.python.org/2.2.1/descrintro.html

Peter

Aug 17 '05 #4

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

Similar topics

2
3197
by: Shozi | last post by:
Dear All, My project is basically about the personal record keeping of user's data. Now user can customize their data entry form by adding/removing the desired fields for personal information (e.g. Add: Home Phone Pin Code, Remove: Personal ID Card No). All this was being done in database and was working fine. Some one recommend me to use DTD/XML to automate this whole process in a standardized way. I started off while searching on...
179
44484
by: SoloCDM | last post by:
How do I keep my entire web page at a fixed width? ********************************************************************* Signed, SoloCDM
35
5192
by: Dr.Tube | last post by:
Hi there, I have this web site (www.DrTube.com) which has the following DTD: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> which switches Mozilla to standards compliance mode as I can confirm myself. How can I check whether IE6 and Opera do so too? TIA Regards Xavier van Unen.
8
6604
by: Dan | last post by:
When a user clicks on a link in my menu, I want the background color of the link that comes up in the hover to remain on the destination page. My menu looks like this: <div id="adminmenu"> <a class="mainlink mainlink1" href="">Events</a><br> <a class="mainlink mainlink2" href="">Home Page Teaser</a><br> <a class="mainlink mainlink3" href="">Testimonials</a><br> <a class="mainlink mainlink4" href="">Repertoire</a><br>
7
2064
by: BarryS | last post by:
Hi All: We're rolling out 3 DB2 (8.2 on LUW) platforms for branch offices, each of these are going to have the same schema. These are all going to be non-federated systems. I need some advice / pointers on keeping the DDL's in sync with each other. I'm going to have a development machine in my office that I first apply any schema / stored-procedure changes to, then would like to roll out
19
2375
by: pinkfloydhomer | last post by:
Please read the example below. I'm sorry I couldn't make it smaller, but it is pretty simple. When client code is calling newThingy(), it is similar to malloc: the client gets a pointer to a chunk of memory that it can use for it's own purposes. But on the "library" side, I want to be able to do some book-keeping for each memory block that I hand out. I want some "hidden" meta-data (that I keep in struct Container) to be associated...
5
9724
by: pb648174 | last post by:
I've been doing a bit of reading and have read in quite a few places that an identity column is a good clustered index and that all or at least most tables should have a clustered index. The tool I used to generate tables made them all with non clustered indexes so I would like to drop all of them and generate clustered indexes. So my questions is a) good idea? and b) how? There are foreign key references to most of them so those would...
1
1678
by: Sjef | last post by:
I am trying to understand the deeper meanings of containers. One would say: everything inside the container div will stay inside, but apparently that's not true. My test code is below. When I run this in IE everything seems fine, when I run it in Firefox the text runs out of the right box and the right box runs out of the overall container. I don't understand the reason for this??? I would like to make both columns the same height while...
399
12974
by: =?UTF-8?B?Ik1hcnRpbiB2LiBMw7Z3aXMi?= | last post by:
PEP 1 specifies that PEP authors need to collect feedback from the community. As the author of PEP 3131, I'd like to encourage comments to the PEP included below, either here (comp.lang.python), or to python-3000@python.org In summary, this PEP proposes to allow non-ASCII letters as identifiers in Python. If the PEP is accepted, the following identifiers would also become valid as class, function, or variable names: Löffelstiel,...
5
12872
by: Thomas Christensen | last post by:
This issue has been raised a couple of times I am sure. But I have yet to find a satisfying answer. I am reading from a subprocess and this subprocess sometimes hang, in which case a call to read() call will block indefinite, keeping me from killing it. The folloing sample code illustrates the problem: proc = subprocess.Popen(,
0
10580
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...
0
10335
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
10323
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
10082
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
9157
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
7621
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
5525
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
5652
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3821
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.