Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > run time linked attributes

Thread Tools

run time linked attributes
Posts: n/a
I've read a few posts about how to have attributes that are "linked" at
run time. I've created a (simple) Python metaclass that accomplishes
this with some behind-the-scenes __init__ redirection. I'm posting the
code at the end in case anyone is interested.

Problem background:
Object a (an instance of class A) has an attribute that points to
object b (which is an instance of class B). So A's __init__ might look
something like this:
self.b = B(arg1, arg2, arg3)

The catch is, that instances of B() need to reference other attributes
of A. The traditional way to do this is pass the instance of A as a
parameter to B. So B's __init__ might look something like:
__init__(self, creator, arg1, arg2, arg3):
self.creator = creator;

naturally, A's __init__ would now look something like:
self.b = B(self, arg1, arg2, arg3)

Essentially this creates two links:
a = A();
a.b --> b
a.b.creator -> a

To hide the passing of the reference to the parent/creator, the
metaclass below adds a method MakeLinkedAttribute.

To hide the handling of the reference to the parent/creator, the
metaclass below redirects B's __init__ when the class object is
created, inserting a call to Meta__init__, which handles the processing
of the parent/creator element. The original __init__ is then called.
See the module's docstring for an example...

I'm curious to hear feedback about the code, especially any dangers
that can occur from redirecting/hijacking __init__.

""" Metaclass for making linked attributes

The LinkedAttribute class allows you to (at run time) have objects
that have references back to the object that created them.

Any class that has LinkedAttribute as it's metaclass will have a
MakedLinkedAttribute() method to make linked attributes.

To accomplish this hackery, we use the metaclass to hijack the
method, replacing it with our own. The new __init__ method (defined
Meta__init__) sets up the _creator attribute (if it was passed in) and
calls the original __init__ function. The original __init__ function
renamed to <class name>_old__init__. The reason for including the
class name
in the first part of the redefinition is so that sub classes that call
super(...).__init__ won't enter an infinite loop.

The restriction to using this metaclass is that the classes that you
MakeLinkedAttribute on must also have LinkedAttribute as a metaclass.

If you use this metaclass, make sure to give credit where credit is
(e.g. in a comment or docstring)

There are other ways of solving the same problem (including passing
parent to __init__ explicitly).

The software is provided AS IS, use this software at your own risk.
is no warranty. By using this software you agree to hold the
harmless of any damage whether direct, incidental, consequently and
otherwise. In no event shall the author(s) of this code be liable for
damages whatsoever incurred by this code.

(c) 2006 Michael Murr [mmurr at code-x d0t net]


from LinkedAttribute import LinkedAttribute

class a(object):
def __init__(self):
self.linked_b = self.MakeLinkedAttribute(b, "this is a linked b")
self.plain_b = b("this is a plain b")

__metaclass__ = LinkedAttribute

class b(object):
def __init__(self, text):
self.text = text
if hasattr(self, "_creator"):
print "I have a creator!"
print "I am a standalone!"

__metaclass__ = LinkedAttribute

if __name__ == "__main__":
objectA = a()
objectB = b("created directly")

print objectA.linked_b.text
print objectA.plain_b.text
print objectB.text


I have a creator!
I am a standalone!
I am a standalone!
this is a linked b
this is a plain b
created directly


class LinkedAttribute(type):
def __new__(klass, klassName, klassBases, klassDict):
# Method to make a new linked child
def MakeLinkedAttribute(self, childClass, *args, **kwds):
return(childClass(_creator=self, *args, **kwds))
# MakeLinkedAttribute(self, childClass, *args, **kwds):

# Run time hijacking of __init__ so we can make
# a _creator BEFORE the original __init__ is called
# We use klassName + "_hijacked__init__" so sub classes
# who call super(...).__init__ won't enter infinite
# loops
# Note: All your __init__ are belong to us
def Meta__init__(self, *args, **kwds):
# If we don't have _creator keyword do nothing
if kwds.has_key("_creator"):
self._creator = kwds["_creator"]
del kwds["_creator"]
# kwds.has_key("_creator"):

# If we don't have an old init, do nothing
if hasattr(self, klassName + "_hijacked__init__"):
attr = getattr(self, klassName + "_hijacked__init__")
attr(*args, **kwds)
# hasattr(self, klassName + "_hijacked__init__"):
# Meta__init__(self, *args, **kwds):

# If we have an init, we need to save it
if klassDict.has_key("__init__"): klassDict[klassName +
"_hijacked__init__"] = klassDict["__init__"]

# Hijack (redirect) __init__ for our [evil] purposes
klassDict["__init__"] = Meta__init__
instance = super(LinkedAttribute, klass).__new__(klass, klassName,
klassBases, klassDict)
instance.MakeLinkedAttribute = MakeLinkedAttribute

# __new__(klass, klassName, klassBases, klassDict):
# LinkedAttribute(type):

Reply With Quote

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
Run-time template list definition / Run-time variable type definition Pierre Yves C++ 2 01-10-2008 02:52 PM
Linked list within a linked list joshd C++ 12 10-02-2006 08:57 AM
Linked list, New try (was:Linked list, no out put,help) fool C Programming 14 07-03-2006 12:29 AM
Generating a char* from a linked list of linked lists Chris Ritchey C++ 7 07-10-2003 10:12 PM
Generating a char* from a linked list of linked lists Chris Ritchey C Programming 7 07-10-2003 10:12 PM