472,975 Members | 1,105 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

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

Need a better understanding on how MRO works?

Given the following code: (I hope it's as simple as possible) :-)
#! /usr/bin/python
import new
class BASE:
def __init__( self ):
print 'Hello from BASE init'
def m1( self ):
print 'M1 Base: Self = ', self

def m1replace( self ):
print 'm1replace:Self = ', self

class D1(BASE):
def __init__(self):
BASE.__init__(self)

def __InitDS101Classes():
name = 'C1'
nclass = new.classobj(name,(D1,),globals())
globals()[name] = nclass
name = 'C2'
nclass = new.classobj(name,(D1,),globals())
globals()[name] = nclass
globals()[name].m1 = m1replace

__InitDS101Classes()

s = C1()
s.m1()
t = C2()
t.m1()

I get the following output:

1100 ./foo1.py
Hello from BASE init
m1replace:Self = <__main__.C1 instance at 0xb7e637cc>
Hello from BASE init
m1replace:Self = <__main__.C2 instance at 0xb7e6388c>

But if I make BASE inherit from object
class BASE(object):
then I get this:

1100 ./foo1.py
Hello from BASE init
m1replace:Self = <__main__.NewClass instance at 0xb7f5070c>
Hello from BASE init
M1 Base: Self = <__main__.D1 instance at 0xb7f5088c>

Can someone please explain why the assignment to C2.m1 would overwrite
BASE.m1?

TIA

--
Time flies like the wind. Fruit flies like a banana. Stranger things have .0.
happened but none stranger than this. Does your driver's license say Organ ..0
Donor?Black holes are where God divided by zero. Listen to me! We are all- 000
individuals! What if this weren't a hypothetical question?
steveo at syslang.net
Aug 25 '07 #1
6 1371
Steven W. Orr <st****@syslang.netwrote:
...
name = 'C1'
nclass = new.classobj(name,(D1,),globals())
globals()[name] = nclass
Here, you're creating a VERY anomalous class C1 whose __dict__ is
globals(), i.e. the dict of this module object;
name = 'C2'
nclass = new.classobj(name,(D1,),globals())
globals()[name] = nclass
and here you're creating another class with the SAME __dict__;
globals()[name].m1 = m1replace
So of course this assignment affects the 'm1' entries in the dict of
both classes, since they have the SAME dict object (a la Borg) -- that
is, IF they're old-style classes (i.e. if D1 is old-style), since in
that case a class's __dict__ is in fact a dict object, plain and simple.

However, if D1 is new-style, then C1.__dict__ and C2.__dict__ are in
fact instances of <dictproxy-- each with a copy of the entries that
were in globals() when you called new.classobj, but DISTINCT from each
other and from globals(), so that further changes in one (or globals)
don't affect globals (nor the other).

I guess this might be a decent interview question if somebody claims to
be a "Python guru": if they can make head or tails out of this mess, boy
the *ARE* a Python guru indeed (in fact I'd accord minor guruhood even
to somebody who can get a glimmer of understanding of this with ten
minutes at a Python interactive prompt or the like, as opposed to
needing to understand it "on paper" without the ability to explore:-).

Among the several "don't"s to learn from this: don't use old-style
classes, don't try to make two classes share the same dictionary, and
don't ask about MRO in a question that has nothing to do with MRO
(though I admit that was a decent attempt at misdirection, it wouldn't
slow down even the minor-guru in any appreciable way:-).
Alex
Aug 26 '07 #2
On Saturday, Aug 25th 2007 at 17:19 -0700, quoth Alex Martelli:

=>Steven W. Orr <st****@syslang.netwrote:
= ...
=> name = 'C1'
=> nclass = new.classobj(name,(D1,),globals())
=> globals()[name] = nclass
=>
=>Here, you're creating a VERY anomalous class C1 whose __dict__ is
=>globals(), i.e. the dict of this module object;
=>
=> name = 'C2'
=> nclass = new.classobj(name,(D1,),globals())
=> globals()[name] = nclass
=>
=>and here you're creating another class with the SAME __dict__;
=>
=> globals()[name].m1 = m1replace
=>
=>So of course this assignment affects the 'm1' entries in the dict of
=>both classes, since they have the SAME dict object (a la Borg) -- that
=>is, IF they're old-style classes (i.e. if D1 is old-style), since in
=>that case a class's __dict__ is in fact a dict object, plain and simple.
=>
=>However, if D1 is new-style, then C1.__dict__ and C2.__dict__ are in
=>fact instances of <dictproxy-- each with a copy of the entries that
=>were in globals() when you called new.classobj, but DISTINCT from each
=>other and from globals(), so that further changes in one (or globals)
=>don't affect globals (nor the other).
=>
=>I guess this might be a decent interview question if somebody claims to
=>be a "Python guru": if they can make head or tails out of this mess, boy
=>the *ARE* a Python guru indeed (in fact I'd accord minor guruhood even
=>to somebody who can get a glimmer of understanding of this with ten
=>minutes at a Python interactive prompt or the like, as opposed to
=>needing to understand it "on paper" without the ability to explore:-).
=>
=>Among the several "don't"s to learn from this: don't use old-style
=>classes, don't try to make two classes share the same dictionary, and
=>don't ask about MRO in a question that has nothing to do with MRO
=>(though I admit that was a decent attempt at misdirection, it wouldn't
=>slow down even the minor-guru in any appreciable way:-).
=>
=>
=>Alex
=>--
=>http://mail.python.org/mailman/listinfo/python-list
=>

Thanks Alex. I am humbled, though I was before I started.
I really don't have a lot of understanding of what you're saying so I'll
probably have to study this for about a year or so.

* (I need to look up what dictproxy is.) I don't have any idea what the
ramifications are of your use of the word DISTINCT. Are you somehow
suggesting that new.classobj does a deep copy of the globals copy that's
passed to it?

* Also, I'd like to understand what the difference is between
nclass = new.classobj(name,(D1,),globals())
vs.
def classfactory():
class somename(object):
def somestuff():
pass
return somename
G1 = classfactory()
globals()[name] = G1

Does new.classobj do anything special?

I appreciate your time.

--
Time flies like the wind. Fruit flies like a banana. Stranger things have .0.
happened but none stranger than this. Does your driver's license say Organ ..0
Donor?Black holes are where God divided by zero. Listen to me! We are all- 000
individuals! What if this weren't a hypothetical question?
steveo at syslang.net
Aug 26 '07 #3
Steven W. Orr <st****@syslang.netwrote:
...
Thanks Alex. I am humbled, though I was before I started.
I really don't have a lot of understanding of what you're saying so I'll
probably have to study this for about a year or so.

* (I need to look up what dictproxy is.) I don't have any idea what the
ramifications are of your use of the word DISTINCT. Are you somehow
suggesting that new.classobj does a deep copy of the globals copy that's
passed to it?
No, most definitely NOT deep!!!, but type.__new__ does "a little" of
what you've said (a shallow copy, which is not quite "a copy" because it
embeds [some of] the entries in slots). new.classobj determines the
metaclass (from the bases, or a __metaclass__ entry in the dictionary)
and calls it to generate the new class. For modern style classes, the
class is type; for old-style legacy classes, it's types.ClassType, and
they're not exactly identical in behavior (of course not, or there would
no point in having both:-).
>
* Also, I'd like to understand what the difference is between
nclass = new.classobj(name,(D1,),globals())
vs.
def classfactory():
class somename(object):
def somestuff():
pass
return somename
G1 = classfactory()
globals()[name] = G1

Does new.classobj do anything special?
No, new.classobj does essentially the same thing that Python does after
evaluating a class statement to prepare the class's name, bases and
dictionary: finds the metaclass and calls it with these arguments.

A key difference of course is that a class statement prepares the class
dictionary as a new, ordinary, distinct dictionary, while new.classobj
accepts whatever dictionary you give it (so you can, though shouldn't,
do strange things such as pass globals()...:-).
Alex
Aug 26 '07 #4
On Saturday, Aug 25th 2007 at 22:14 -0700, quoth Alex Martelli:

=>Steven W. Orr <st****@syslang.netwrote:

=>* Also, I'd like to understand what the difference is between
=> nclass = new.classobj(name,(D1,),globals())
=>vs.
=> def classfactory():
=> class somename(object):
=> def somestuff():
=> pass
=> return somename
=> G1 = classfactory()
=> globals()[name] = G1
=>>
=>Does new.classobj do anything special?
=>
=>No, new.classobj does essentially the same thing that Python does after
=>evaluating a class statement to prepare the class's name, bases and
=>dictionary: finds the metaclass and calls it with these arguments.
=>
=>A key difference of course is that a class statement prepares the class
=>dictionary as a new, ordinary, distinct dictionary, while new.classobj
=>accepts whatever dictionary you give it (so you can, though shouldn't,
=>do strange things such as pass globals()...:-).

In fact, I wanted to make a common routine that could be called from
multiple modules. I have classes that need to be created from those
multiple modules. I did run into trouble when I created a common routine
even though I passed globals() as one of the args. The """though
shouldn't""" is prompting me to ask why, and where I might be able to read
more.

--
Time flies like the wind. Fruit flies like a banana. Stranger things have .0.
happened but none stranger than this. Does your driver's license say Organ ..0
Donor?Black holes are where God divided by zero. Listen to me! We are all- 000
individuals! What if this weren't a hypothetical question?
steveo at syslang.net
Aug 26 '07 #5
Steven W. Orr <st****@syslang.netwrote:
...
=>accepts whatever dictionary you give it (so you can, though shouldn't,
=>do strange things such as pass globals()...:-).

In fact, I wanted to make a common routine that could be called from
multiple modules. I have classes that need to be created from those
multiple modules. I did run into trouble when I created a common routine
even though I passed globals() as one of the args. The """though
shouldn't""" is prompting me to ask why, and where I might be able to read
more.
The dictionary you pass to new.classobj should be specifically
constructed for the purpose -- globals() will contains all sort of odds
and ends that have nothing much to do with the case.

You appear to be trying to embody lot of black magic in your "common
routine", making it communicate with its callers by covert channels; the
way you use globals() to give that routine subtle "side effects" (making
the routine stick entries there) as well as pass it an opaque,
amorphous, unknown blobs of input information, strongly suggests that
the magic is running away with you (a good general reference about that
is <http://video.google.com/videoplay?docid=4611491525028588899>).

"Explicit is better than implicit", "simple is better than complex",
etc, can be read by typing ``import this'' at an interactive Python
prompt.

The best book I know about the do's and don't's of large-scale software
architecture is Lakos' "Large-Scale C++ Software Design",
<http://www.amazon.com/Large-Scale-So...kos/dp/0201633
620-- very C++ specific, but even though some of the issues only apply
to C++ itself, many of its crucial lessons will help with large scale SW
architecture in just about any language, Python included.

What I had to say about the lures and pitfalls of black magic in Python
specifically is spread through the Python Cookbook 2nd edition (and, to
a lesser extent, Python in a Nutshell).
Alex
Aug 26 '07 #6
On Sun, 26 Aug 2007 07:55:39 -0400, Steven W. Orr wrote:
In fact, I wanted to make a common routine that could be called from
multiple modules. I have classes that need to be created from those
multiple modules. I did run into trouble when I created a common routine
even though I passed globals() as one of the args.
I'm thinking that you should cross out "even though" and insert
"because" :-)

Perhaps I'm misunderstanding exactly what you're trying to accomplish,
but if you want to call a routine (a function? class?) from multiple
modules, the simplest way is the best: create the routine in one module,
then import it into all the others.

--
Steven.
Aug 26 '07 #7

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

Similar topics

9
by: netpurpose | last post by:
I need to extract data from this table to find the lowest prices of each product as of today. The product will be listed/grouped by the name only, discarding the product code - I use...
4
by: Muhd | last post by:
It seems like im missing something, what i want to do is select the last row from a table that relates to a specific person. My table and select statement follow, the select statement works fine,...
19
by: James Fortune | last post by:
I have a lot of respect for David Fenton and Allen Browne, but I don't understand why people who know how to write code to completely replace a front end do not write something that will automate...
7
by: Buck Rogers | last post by:
Hi all! Newbie here. Below is an example from Teach Yourself C in 21 Days. My apologies if it is a bit long. What I don't understand is how the "get_data" function can call the...
5
by: Y2J | last post by:
I am working through this book on C++ programming, the author is speaking of using linked lists. He gave and example which I found confusing to say the least. So I rewrote the example in a way that...
22
by: JoeC | last post by:
I am working on another game project and it is comming along. It is an improvment over a previous version I wrote. I am trying to write better programs and often wonder how to get better at...
9
by: sam_cit | last post by:
Hi Everyone, I have the following structure and i have a function that will work(modify/edit) the members of the structure, please tell me which is a better apprach considering both time and...
15
RMWChaos
by: RMWChaos | last post by:
In my ongoing effort to produce shorter, more efficient code, I have created a "chicken and egg" / "catch-22" problem. I can think of several ways to fix this, none of them elegant. I want my code...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
0
by: Aliciasmith | last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
0
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
4
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

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.