473,386 Members | 1,715 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Classes referencing each other

Hello list,

I have searched for some time now, but no result...
I'm having the following problem:

In a module I have a huge number of classes of the form:

class A(object):
connected_to = [B, C]
<other attributes...>

class B(object)
connected_to = [C]
<other attributes...>

class C(object)
connected_to = [A]
<other attributes...>

As you see, classes A and B reference classes that
are not yet defined when the class is being defined.
It will raise a NameError: 'B'.

I know i could solve this by leaving out the definition
of 'connected_to' in A and attach it to the class later on by
A.connected_to = [B, C]
but I would like to avoid this, because in the module
there are about 50 classes that have to be altered from time
to time and it's just incredibly ugly if I have to look for
the attribute definitions in more than one place.

Also, I would like to avoid eval(), because the references
have to be followed very often and that would cause more
CPU load and make the program code uglier :)

If anyone of you knows a neat way to solve this, I'd be
very grateful.

Greetings,
Manuel
Sep 1 '06 #1
7 4876
"Manuel Bleichner" <ma****@prolink.dewrote:
If anyone of you knows a neat way to solve this, I'd be
very grateful.
You could use a function:

class A(object):
@staticmethod
def connected_to(): return [B, C]
<other attributes...>

class B(object)
@staticmethod
def connected_to(): return [C]
<other attributes...>

class C(object)
@staticmethod
def connected_to(): return [A]
<other attributes...>

for cls in globals().values():
if (type(cls) is type and
hasattr(cls, 'connected_to') and
callable(cls.connected_to)):
cls.connected_to = cls.connected_to()

or just store the names of the classes and do a similar fixup once they are
all defined:

class A(object):
connected_to = ['B', 'C']
<other attributes...>

for cls in globals().values():
if (type(cls) is type and
hasattr(cls, 'connected_to')):
cls.connected_to = [globals()[c] for c in cls.connected_to ]
Sep 1 '06 #2
Manuel Bleichner wrote:
Hello list,

I have searched for some time now, but no result...
I'm having the following problem:

In a module I have a huge number of classes of the form:

class A(object):
connected_to = [B, C]
<other attributes...>

class B(object)
connected_to = [C]
<other attributes...>

class C(object)
connected_to = [A]
<other attributes...>

As you see, classes A and B reference classes that
are not yet defined when the class is being defined.
It will raise a NameError: 'B'.

I know i could solve this by leaving out the definition
of 'connected_to' in A and attach it to the class later on by
A.connected_to = [B, C]
but I would like to avoid this, because in the module
there are about 50 classes that have to be altered from time
to time and it's just incredibly ugly if I have to look for
the attribute definitions in more than one place.
You could move all connections to a central location after the
class definitions, such as

class A: pass
class B: pass
class C: pass

connections = {A: (B, C), B: (C,), C: (A,)}

Georg
Sep 1 '06 #3
Thanks for your answer :)
You could use a function:

class A(object):
@staticmethod
def connected_to(): return [B, C]
<other attributes...>
I already thought about such a solution, but since
my code has to be compatible with python 2.3, i would
have to use the connected_to = staticmethod(connected_to)
syntax, which bloats the code and makes it quite unreadable.

or just store the names of the classes and do a similar fixup once they
are
all defined:

class A(object):
connected_to = ['B', 'C']
<other attributes...>

for cls in globals().values():
if (type(cls) is type and
hasattr(cls, 'connected_to')):
cls.connected_to = [globals()[c] for c in cls.connected_to ]
This solution seems good to me. It won't work for me as it is,
because the structure of the classes is actually a bit more
complex, but it pushed me in the right direction.

Thanks again,
Manuel
Sep 1 '06 #4
Manuel Bleichner wrote:
Hello list,

I have searched for some time now, but no result...
I'm having the following problem:

In a module I have a huge number of classes of the form:

class A(object):
connected_to = [B, C]
<other attributes...>

class B(object)
connected_to = [C]
<other attributes...>

class C(object)
connected_to = [A]
<other attributes...>

As you see, classes A and B reference classes that
are not yet defined when the class is being defined.
It will raise a NameError: 'B'.

I know i could solve this by leaving out the definition
of 'connected_to' in A and attach it to the class later on by
A.connected_to = [B, C]
but I would like to avoid this, because in the module
there are about 50 classes that have to be altered from time
to time and it's just incredibly ugly if I have to look for
the attribute definitions in more than one place.
So why can't you do it all in one place by
A.connected_to = [B, C]
B.connected_to = [C]
C.connected_to = [A]
?

or by a tabular method:

connections = (
(A, [B, C]),
(B, [C]),
(C, [A]),
)
for cls_from, targets in connections:
# maybe insert some checking code in here ...
# is X.connected_to = [X] allowed?
# is Y.connected_to = [] allowed?
cls_from.connected_to = targets
>
Also, I would like to avoid eval(), because the references
have to be followed very often and that would cause more
CPU load and make the program code uglier :)
Avoiding eval() does always seem to be a good thing :-)

BTW, care to tell us what the connections mean? Applications of
connected instances of the one class are of course very common, but 50
classes connected in a cyclic fashion is rather new to me ...

Cheers,
John

Sep 1 '06 #5
Thanks for the answer.
You could move all connections to a central location after the
class definitions, such as

class A: pass
class B: pass
class C: pass

connections = {A: (B, C), B: (C,), C: (A,)}

I think I simplified my classes a bit too much :)
Actually there are multiple types of connections between
the classes. for example:

class A(CableConnected, WLANConnected):
name = 'I am class A'
cable_connections = [B, C]
wlan_connections = [D]

class B(CableConnected, RadioConnected):
name = 'I am class B'
cable_connections = [C, A]
radio_connections = [F]
....

And because not all classes have the same types of connections,
it would become extremely unreadable to try to define them
at a central place. Also it seperates attributes from each other;
'name' is defined in the class, the connections somewhere else.

Greetings,
Manuel
Sep 1 '06 #6
Hi, thanks for your answer, too :)

Your solution won't do it, because of reasons I explained
in the answer to Georg Brandl.
BTW, care to tell us what the connections mean? Applications of
connected instances of the one class are of course very common, but 50
classes connected in a cyclic fashion is rather new to me ...
Okay, I didn't want to do this, because some of you would
think I'm crazy, but what the heck :D

I'm programming a browsergame which is split in multiple parts.
There is a core which is running all the time and a cgi client connecting
to it. The core maintains all classes and keeps the game running, while
the client only requests data from it.
The core of course needs to hold all the definitions for the game
(e.g. units, buildings, resources, research) - these are written as
classes.

class EMCenter(Building, Researcher, Constructor, OnLand):
maxhitpoints = 1000
researchspeed = 70
constructspeed = 50
research_costs = [SmallEM, Weapons, Shields]
resource_costs = [Iron: 500, Granite: 300, Silicon: 150]
possible_research = [MediumEM, EMWeapons, EmShockwave]
possible_constructs = [Razor, Lancer, Stinger] # these are
all units

Now when a certain unit should be built, it must be checked if
the requirements are matched.
=check research_costs and resource_costs
After building it, an instance of the class will be created.
The new object can itself build (=Constructor) and research
(=Researcher) the items provided in possible_constructs and
possible_research.

The problem occured when i wanted to define a unit that can
construct a building which itself is able to construct that
unit.

Absolutely overkill for a browsergame, I know, but I like the concept =)
Manuel
Sep 1 '06 #7
Does the "EMCenter" really need to /subclass/ from all of those? Or
would it be better to make some of those attributes of an EMCenter
INSTANCE (passing in instances of the others to the __init__() ).

class EMCenter(object):
def __init__(self, b, r, c, ol):
self.building = b
self.researcher = r
...

IOW: the difference between:
an EMCenter IS a building AND
IS a researcher AND
IS a constructor AND
IS a "OnLand"
=These relations are correct:
the EM Center can build units and research technologies, therefore
it is a researcher and constructor.

Note that "OnLand" already sounds like an attribute -- and at that,
maybe an attribute of "Building"
Yes, this one is really an attribute, but it's not yet implemented and
I wasn't sure how to do it when I wrote the template code.

As soon as you get a recursive definition, you MUST split...
Yes =(
I'll have to try to reduce such relations to a minimum...
It would have just been nice to declare and later define the classes,
but such a feature would bloat the neat python syntax.

Thanks for all the text you wrote, but it all went a bit in the
wrong direction, sorry :)
Manuel

Sep 4 '06 #8

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

Similar topics

18
by: Edward Diener | last post by:
Is the packing alignment of __nogc classes stored as part of the assembly ? I think it must as the compiler, when referencing the assembly, could not know how the original data is packed otherwise....
6
by: Tappy Tibbons | last post by:
I do not know exactly how to explain what I am asking for, but here goes... Say I have a simple set of classes: ========= Public Class clsPerson Public FirstName As String Public LastName As...
6
by: STom | last post by:
I have a class declare like this: <Serializable>Public Class Talk Public Structure _localTalk Public _iTalkNumber as Integer End structure End Class I can see the structure from other...
3
by: Brian Bischof | last post by:
I'm having troubles getting the debugging process to work consistenly for external classes. I got it to work once and then I turned it off. But now I can't get re-enabled. Here is what I'm doing....
3
by: jason | last post by:
Please pardon my completely lack of understanding on the topic. I have a website I developed with another developer. We are both far from experts in VB.NET and OOP. We developed the site WITHOUT...
7
by: Adrian Hawryluk | last post by:
Can one define a partial class (first part containing constants like enums) and then define the rest of the class elsewhere? I ask this because I've had in the past needed to defined two classes...
20
by: Auddog | last post by:
I'm new to working with classes. I'm pretty much a self taught php programmer that uses php mostly for database entry and listings. I would like to expand my talents and start working with...
2
by: =?Utf-8?B?V2ViQnVpbGRlcjQ1MQ==?= | last post by:
Ok this is for other who like me just can't get enough of complications! i have two app_code directories one for cs and one for vb it works ok, but now i need to reference a cs class from a vb...
1
by: puzzlecracker | last post by:
Hello Group, Say I have classes A and B and the both need to maintain a pointer/ reference to each for various reasons, say optimization. And there are other classes in the project use these...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
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...
0
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,...
0
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...

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.