How can a function find the function that called it?

K

kj

I want to implement a frozen and ordered dict.

I thought I'd implement it as a subclass of collections.OrderedDict
that prohibits all modifications to the dictionary after it has
been initialized.

In particular, calling this frozen subclass's update method should,
in general, trigger an exception ("object is not mutable").

But OrderedDict's functionality *requires* that its __init__ be
run, and this __init__, in turn, does part of its initialization
by calling the update method.

Therefore, the update method of the new subclass needs to be able
to identify the calling function in order to make a special allowance
for calls coming from OrderedDict.__init__. (Better yet, it should
be able to allow calls coming from its own class's __init__, via
OrderedDict.__init__.)

The best I've been able to do is to use inspect to get the name of
the calling function. For the case I'm trying to identify, this
name is simply "__init__".

But Python code is awash in __init__'s...

Is it possible to achieve a more precise identification? Specifically,
I want to know the *class* (not the file) where this '__init__' is
defined.

(BTW, I don't understand why inspect doesn't provide something as
basic as the *class* that the method belongs to, whenever applicable.
I imagine there's a good reason for this coyness, but I can't figure
it out.)

TIA!

~kj
 
C

Chris Gonnerman

I want to implement a frozen and ordered dict.

I thought I'd implement it as a subclass of collections.OrderedDict
that prohibits all modifications to the dictionary after it has
been initialized.

In particular, calling this frozen subclass's update method should,
in general, trigger an exception ("object is not mutable").

But OrderedDict's functionality *requires* that its __init__ be
run, and this __init__, in turn, does part of its initialization
by calling the update method.
Use a flag, "private" to your new class, to indicate whether
initialization is complete or not; your update method would see that
initialization is not yet complete when called by __init__, and so it
would do its business (calling the class method). At the end of the
__init__ function, set the initialized property to true. If your update
is called with the initialized property already set to true, it will
raise the exception.
 
C

ChasBrown

I want to implement a frozen and ordered dict.

I thought I'd implement it as a subclass of collections.OrderedDict
that prohibits all modifications to the dictionary after it has
been initialized.

In particular, calling this frozen subclass's update method should,
in general, trigger an exception ("object is not mutable").

But OrderedDict's functionality *requires* that its __init__ be
run, and this __init__, in turn, does part of its initialization
by calling the update method.

Rather than trying to identify the caller, I'd do something like:

class FrozenODict(OrderedDict):

def __init__(self, *args, **kwargs):
OrderedDict.__init__(self, *args, **kwargs)
self.update = self._update # init is complete, so override
# update method for this instance

def _update(self, dict2):
raise Exception("object is immutable!!")

After the __init__, calls to the instance's 'update' function will be
mapped to _update. It's essentially overriding the inherited function
on the fly.

Cheers - Chas
 
D

Daniel Urban

(BTW, I don't understand why inspect doesn't provide something as
basic as the *class* that the method belongs to, whenever applicable.
I imagine there's a good reason for this coyness, but I can't figure
it out.)

One function object can "belong to" (be in the namespace of) more than
one class, so there is no "the class".
 
J

John Nagle

That's actually a fairly common question - is an object in
initialization, or has it been fully created? It would be useful
if Python had some standard way to check if initialization
has completed. Sometimes a parent class needs to know if
initialization of the entire object has completed. This typically
comes up with classes that define "__setattr__" and are then
subclassed.


John Nagle
 
K

kj

One function object can "belong to" (be in the namespace of) more than
one class, so there is no "the class".

There are many other properties that inspect reports on (e.g.
filename) that may not apply to an individual case. For 99.9% of
methods, the class in which it was lexically defined would be good
enough.
 
M

Mark Wooding

kj said:
But OrderedDict's functionality *requires* that its __init__ be
run, and this __init__, in turn, does part of its initialization
by calling the update method.

Therefore, the update method of the new subclass needs to be able
to identify the calling function in order to make a special allowance
for calls coming from OrderedDict.__init__

That doesn't follow at all. Why not set a `frozen' flag when your
initialization is complete? Something like

class ImmutableOrderedDict (OrderedDict):
def __init__(me, *args, **kw):
me._frozen = False
OrderedDict.__init__(me, *arg, **kw)
me._frozen = True
def _check(me):
if me._frozen:
raise ImmutableError

And so on.

Thank you for explaining your actual objective, by the way.

-- [mdw]
 
D

DevPlayer

Original Poster
I thought I'd implement it as a subclass of collections.OrderedDict
that prohibits all modifications to the dictionary after it has
been initialized.

I thought the __new__() method was for customizing how objects where
instantated. Where in __new__() you would get an object instance and
then usually initialize the public data attributes in __init__().
Although I like Mark Wooding's solution as it's clean and easy to
understand.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top