Is there a reason not to do this?
Carl Banks
pavlovevidence at gmail.com
Fri Dec 1 09:27:06 EST 2006
Ron Garret wrote:
> In article <rNOSPAMon-ACA0D1.23364830112006 at news.gha.chartermi.net>,
> Ron Garret <rNOSPAMon at flownet.com> wrote:
> > I don't want to get into a philosophical debate.
>
> Actually, I changed my mind. Consider:
>
> def g(): print 'G'
>
> def h(): print 'H'
>
> def f(): g()
>
> class C1:
> def m1(self): f()
>
> class C2:
> def m1(self): g()
>
> c1 = C1()
> c2 = C2()
>
> def f(): h()
>
> class C2:
> def m1(self): h()
>
> c1.m1() # Prints H
> c2.m1() # Prints G
>
> On what principled basis can you justify two different outputs in this
> case? Why should I be able to change the definition of f and not have
> to go back and recompile all references to it, but not m1?
I see what you were asking now: you want to know why a class statement
doesn't modify a previously existing class (as is the case in Ruby)
rather than to create a new one.
The principle behind this is pretty much "it was just a language design
decision".
The designers of Python felt it was generally best to have whole
classes in one place, rather than spread out over many locations. I
tend to agree with this. Changing classes in-place violates the
"principle of least surprise"--keep in mind the "surprise" we're
talking about is the reader's surprise, not the writer's. A person
might be reading a class definition wondering, "WTF is happening, why
doesn't it match the behavior?", not knowing that the class was
modified in-place somewhere else. (That person could be you three
months later.)
Valid use cases like yours are exceptional, and can be done
straightforwardly without changing class statement to modify in-place,
so I think it was the right decision.
Your opinion may differ. It doesn't seem to have wreaked havoc in
Common Lisp and Ruby. But that's not how Python is. I have things I
don't like about Python, too. You just deal with it.
P.S. If you want to be truly evil, you could use a class hook to get
the modifying in-place behavior:
def modify_in_place(name,bases,clsdict):
cls = globals()[name]
for attr,val in clsdict.iteritems():
setattr(cls,attr,val)
return cls
# Replace second C2 class above with this
class C2:
__metaclass__ = modify_in_place
def m1(self): h()
Carl Banks
More information about the Python-list
mailing list