Basic inheritance question

Lie Lie.1296 at gmail.com
Sun Jan 20 17:37:56 EST 2008


On Jan 16, 9:23 pm, Bjoern Schliessmann <usenet-
mail-0306.20.chr0n... at spamgourmet.com> wrote:
> Lie wrote:
> > 42.desthuilli... at wtf.websiteburo.oops.com> wrote:
> >> I used to systematically use it - like I've always systematically
> >> used 'this' in C++  and Java.
>
> > And that is what reduces readability.
>
> IMHO not, IOPHO not. This is the nth time (n >> 1) this discussion
> comes up here. If I have learned one thing from those very lengthy
> discussions, it's that Python's "self" handling is not going to
> change.

And ah... yes, I don't wish it go away either. In VB, excessive Me
reduces readability, but in Python it doesn't.

> > A proficient VB/C/Java programmer would frown upon the extra,
> > unneeded garbage as they thought it was clear already that the
> > variable refers to a class-level variable.
>
> C programmers surely have no opinion concerning C because it has no
> native classes.

C-family, ok? Please stop taking my words to its letters.

> Personally, I've seen many C++ programs with complex class designs
> where it definitely helps to consistently use "this->". I cannot
> remember all local (and global) variables in bigger methods.

In that case, you have the _option_ to do it.

> > There is one major positive point: convenience and shorter code.
> > (isn't that two?)
>
> Shorter code is not per se positive, neither is it convenient. If it
> was, everyone would use perl.

Not always, but sometimes it do help not to be obliged to use the
class name especially in short, simple programs (as opposed to big
projects that requires hundreds of thousands of lines of code) that is
changed frequently (being in heavy development). A good real-life
example for this would be for new learner of programming or the
language, they would write a lot of ten liners that is changed a LOT
of times due to their (yet) incomplete understanding of the concepts.

> >> it's the first argument of the function - which usually happens to be
> >> the current instance when the function is used as a method.
>
> > And that's the point, self (or anything you name it) is almost always
> > the current instance
>
> # this is a plain function. In this function,
> # 'obj' can be whatever that happens to have a (numeric)
> # 'stuff' attribute
> def func(obj, arg):
>    return (obj.stuff + arg) / 2.0
>
> # this is a class with an instance attribute 'stuff'
> class Foo(object):
>     def __init__(self, bar):
>       self.stuff = bar + 42
>
> # this is another (mostly unrelated) class
> # with a class attribute 'stuff'
> class Bar(object):
>    stuff = 42
>
> # this is a dummy container class:
> class Dummy(object): pass
>
> # now let's play:
> import new
>
> d = Dummy()
> d.stuff = 84
> print func(d, 1)
>
> d.baaz = new.instancemethod(func, d, type(d))
> print d.baaz(2)
>
> f = Foo(33)
> print func(f, 3)
> Foo.baaz = func
> f.baaz(4)
>
> print func(Bar, 5)
> Bar.baaz = classmethod(func)
> Bar.baaz(6)
>
> >  and that makes it functionally the same as Me and
> > this in VB and Java.
>
> Depends on the context, cf above !-)

Please again, stop taking letters to the words, I don't meant them to
be exactly the same, rather the same would meant that they generally
can be considered equal, exceptions exists of course. And btw, I don't
understand what you meant by your example, they seemed to be a
completely OK program for me, even though it's a bit confusing to
follow[2].

[2] btw, the reason it's a bit confusing to follow is one of my
points: It is a Bad Thing(tm) to use the same name for different
variables even in a language like Python that enforce explicit naming
of classes

> >>> Most other languages
> >>> 1) automatically assign the containing class' object
> >> s/containing class' object/current instance/
>
> >>> in a keyword
> >>> (Java: this, VB: Me) behind the screen,
>
> >> That's not very far from what a Python method object does -
> >> automatically assign the current instance to something. The difference
> >> is that Python uses functions to implement methods (instead of having
> >> two distinct contructs), so the only reliable way to "inject" the
> >> reference to the current instance is to pass it as an argument to the
> >> function (instead of making it pop from pure air).
>
> > It isn't very far, but Python makes it obvious about the assignment
> > (not behind the screen).
>
> Exactly. And given both the simplicity of the solution and what it let
> you do, that's a *very* GoodThing(tm) IMHO.

I agree, it's a Good Thing but it doesn't make the point less pointy,
the difference between Me/this and self is just the explicit
assignment. Other things that is possible because of the explicit
assignment is just a "coincidence" of design choice.

> >>> and 2) automatically searches
> >>> variable name in both the local variable table and the containing
> >>> class variable table  (so to refer to a class variable named var from a
> >>> method inside the class, we only need to write var, not self.var as in
> >>> python).
> >> This - as you know - cannot work well with Python's scoping rules and
> >> dynamicity. Anyway, implicit object reference is definitively a
> >> BadThing(tm) wrt/ readbility, specially with multiparadigm languages
> >> (like Python or C++). Why do you think soooo many C++ shops impose the
> >> m_something naming scheme ?
>
> > Implicit object reference for the containing class has little harm, if
> > a class is so complex that there are more than 10 class-level
> > variable, then it is obvious that that class needs to be fragmented to
> > smaller classes.
>
> Not necessarily. There are general rules (like 'keep your classes small
> and focused', which I wholefully agree with), there are guidelines (like
> 'more than 10 member variables might smell like refactoring), and
> there's real life, where one very often faces classes that have much
> more than 10 member variables and still are as small and focused as
> possible.

I'd add "whenever possible" then.

I don't consider 10 as a guideline, but rather as a large number I
randomly picked for an example, because in most project 10 is A LOT
for number of variables, and I'm sure that most well designed program
would have less than 10 variables per class (except in cases where it
is just impossible to fragment the class any further).

> > Remembering less than 10 variable and avoiding naming
> > collision among just 10 variable is not hard (and 10 is really too
> > many, most classes should only use 2-4 variables),
>
> I really doubt you'll be able to write any working non-trivial software
> trying to strictly follow this rule.

In what way have I said that the rule is strict? No rule is ever
strict in my book, ALL rules are meant to be bend in exceptional cases
and ALL exceptions are meant to be excepted themselves (applying the
definition recursively).

> > especially if you
> > have a good IDE that employs Intellisense-like technology (IDLE has
> > it).
>
> IDLE is certainly not a "good IDE" in my book.

What you've just said actually enforce the sentence, even a bad IDE
like IDLE have Intellisense-like feature :)
I agree that IDLE isn't a good IDE, but it is an example that I could
use since it is the only Python IDE I have ever used (although I'm
interested to find another, the demand isn't that high ...yet... to
_have_ to find another IDE)

> > And it is always a Bad Thing(tm) to use the same name for two
> > variable in the class and in function (which is the main and only
> > source of possible ambiguity) in ANY language, even in Python.
>
> Ho, yes.... Like, this would be bad ?
>
> class Person(object):
>    def __init__(self, firstname, lastname, birthdate, gender):
>      self.firstname = firstname
>      self.lastname = lastname
>      self.birthdate = birthdate
>      self.gender = gender
>
> C'mon, be serious. It's often hard enough to come with sensible names,
> why would one have to find synonyms too ? Try to come with something
> more readable than the above, and let us know. Seriously, this braindead
> rule about  "not using the same name for an attribute and a local var"
> obviously comes from languages where the "this" ref is optional, and
> FWIW it's obviously the wrong solution to a real problem (the good
> solution being, of course, to use the fully qualified name for
> attributes so there's no possible ambiguity).

The code fragment you've given way above (about the Foo, Bar, bazz,
and func) also suffers from the bad habits of using the same name for
different variables.

And it's not a "braindead" rule (even though I used the word always,
it still isn't a braindead always without exceptions)

The example you've given IS the most readable form since the function
is _simple_, consider a function that have complex codes, possibly
calculations instead of simply assigning initial values I'm sure you'd
slip up between the self.* variables and the * variables once or
twice, possibly becoming the source of hard-to-find bugs. In other
hand in a _complex_ function, if you thought of a new name, like
initialfirstname, etc you'd know what is what and what is where
immediately

And in languages that doesn't enforce explicit naming of classes, when
there is the two or more same names, the one with the smallest scope
is picked, so in _simple_ functions, the trick of using full qualified
names and overloaded local names is still possible and feasible. In
complex functions, the trick fails even in Python, because even if
Python and our full-concentration-brain is aware of the difference
between self.* and *, our spreaded-concentration-brain that is
scanning the code for the source of bugs might get stumbled on the
confusing use of self.* and *.

> >> Anyway, I actually know 3 languages (4 if C# works the same) that has
> >> this implicit 'this' (or whatever the name) 'feature', and at least 5
> >> that don't. So I'm not sure that the "most other languages" qualifier
> >> really applies to point 2 !-)
>
> > What's this 5 languages?
>
> Smalltalk, Python, PHP, javascript, Ruby. I don't remember how Scheme,
> CLOS and OCaml handle the case.

Among all them, only Javascript is considerably mainstream.
Javascript, being virtually the only web-based scripting language that
is supported by most browsers.

> > Are they a mainstream, high-level languages
> > or lesser known, low-level languages? C-family, Java, and Basic are
> > the Big Three of high-level programming language.
>
> None of C, C++, Java nor Basic qualify as "hi-level". C is the lowest
> possible level above assembly, C++ is often refered to as an "object
> oriented assembler", Java is way too static, crippled, verbose an
> unexpressive to qualify as "hi-level" (even if it suffers from some
> problems usually associated with higher level languages). I won't even
> comment on basic (is that really a language at all ?).

Your criteria on being high-level is simply just odd. The rest of the
world recognizes C-family, Java, and Basic as high-level languages. I
agree C is a lower-level language compared to C++, C#, Basic, and
Python, but standing by itself, it still qualifies as high-level
language.

If I have to say it, Python is actually lower level than Basic. While
Java is just below Python and C and C++ is just below Java. Why do I
consider Basic the highest-level? Because it is the cleanest to scan
(no confusing symbols, i.e. no curly braces, no confusing use of
parens (Python uses (), [], and {}, VB only use ()[3]), and that is
also the reasons of some of its warts.

In what way C++ resembles an assembler? Have you ever programmed in
assembly? How hard is it to create a simple program in assembly? And
how hard is it to create a complex program in C++ (which AFAIK is used
by hundreds of mega projects including CPython)?

And have you ever used Basic at all?
Some programmers would instantly frown upon Basic, simply because they
don't know that Basic is "just another language". Apart from a syntax
that is very different from most languages (absence of curly braces,
the minimal use of non-alphabet characters in the syntax, minimal use
of short keywords, opting for keywords that is (hopefully)
understandable to non VBers[4]), and apart from the quality of the
implementation, the language itself isn't a bad language. Sure they
may have some warts, but I dare to say "Python have no warts".

[3] In fact the new VB.NET 2008 adds a syntax that uses curly braces
to VB, but it's only for a syntax sugar, in Python, the difference
between the different kind of parentheses is significant.
[4] The only significant exception to, a (hopefully) understandable
keyword names to non-VBers, is probably the most important keyword,
"Dim" for variable declaration.

> >>> In VB, Me is extremely rarely used,
> >> I used to systematically use it - like I've always systematically used
> >> 'this' in C++  and Java.
>
> > And that is what reduces readability. A proficient VB/C/Java
> > programmer
>
> There are quite a few proficient C/C++/Java programmers here. As far as
> I'm concerned, I would not pretend being one - I just have a good enough
> knowledge of C, Java and (alas) VB to be able to get up to speed in a
> reasonnable time frame.
>
> As a side note, the problem just doesn't exists in C, which has
> absolutely no support for OO.

When I said C, it might mean C and C-family, so please stop
misunderstanding me.

As a side note, the conversation we're just having is a real life
example of using the name C when it means C-family, your mindset
instantly protest that C doesn't have objects, while my mindset says
"C" can't have meant C as a language since I don't state C++ and C#
too while I should have, and knowing the fact that C in C-family
doesn't have objects would make it clear that it is an exception.

I'm not saying my mindset is better than yours (it have its positives
and negatives), in fact I apologize for getting you confused.

> > would frown upon the extra, unneeded garbage as they
> > thought it was clear already that the variable refers to a class-level
> > variable.
>
> In C++, the canonical way to make this "clear" is to use the m_name
> convention. There must be some reason C++ programmers feel a need for
> this "extra, unneeded garbage" ?-)

In some cases, an extremely complex class that can't be fragmented any
further, the m_ convention is surely useful, but in most cases you
could skip them out. And the canonical way to make this "clear" is not
the m_ convention, it's the name itself. A well-designed class would
choose names that is recognizable instantly from the name itself, even
without the pseudo-name appended to it (or prepended).

btw you must have been memorizing names braindeadly, because the only
way you could stumble on that is by memorizing names braindeadly.
Names shouldn't be memorized, it should be inferred and memorized. For
example, when you met a variable name firstname and lastname inside a
class called Person, you'd immediately realize that it is Class Level
variable because you know that the function you're currently working
on use the name initialfirstname and initiallastname.

> > It is a different story if, like Python, the use of self is
> > enforced by the language, the self wouldn't be viewed as extra
> > unnecessary garbage.
> >>> in Python, self is all
> >>> over the place. Well, there is positive and negative to both sides,
> >>> convenience in VB, and flexibility in Python.
> >> As far as I'm concerned, there's *no* positive point in implicit object
> >> reference, and there has never been (and before some paranoid nutcase
> >> around accuse me of overzealous biggotry : I already held this very same
> >> opinion years before I discovered Python).
>
> > There is one major positive point: convenience and shorter code.
> > (isn't that two?)
>
> These are not rated as "positive" in my book. That's perhaps why Python
> is so far MFL ?

Not in _your_ book. Different languages have been devised throughout
the world to solve various problems, some of which are convenience in
using the language itself.

> > As I've pointed out, there is little harm in class-level variable's
> > implicit reference.
>
> Have some working experience on any non-trivial C++ project ?

No (you could say I'm a student so I've never "worked"[1]). But I've
done some medium-sized projects in other languages.

[1] If you understand the irony, you'd realized I was deliberately
misunderstanding you

> >>> Compare the following codes:
> >>> VB.NET:
> >>> Public Class A
> >>>     Dim var
> >>>     Public Function aFunction()
> >>>         return var
> >> Add three levels of inheritence and a couple globals and you'll find out
> >> that readability count !-)
>
> > It's the mental model that have to be adapted here, if the current
> > class is inheriting from another class, you've got to think it as
> > names from parent class as it is a native names, so you don't actually
> > need to know where the variable comes from
>
> In C++ (and VB IIRC), it might as well be a global So sorry but yes, I
> have to know where it comes from.

How many times would you use globals, it is a Bad Thing(tm) to use
globals in the first case. In some exceptional cases globals might be
unavoidable, but it is trivial to work out that you have to reduce the
amount of globals to a minimum, in almost any cases to a number you
can use a hand to count with. And applying the hacks mentioned, why
don't you use the m_ convention for globals, and retains the
convenience of m_-free variables in your class variable. You use class
variable much more often than globals, and in most projects class-
level variable is used just as often as local-variable.

> > since knowing where it
> > comes from is breaking the encapsulation
>
> Nope, it's knowing what you're doing and how the piece of software at
> hand is working. And FWIW, while data hiding is one possible mean of
> encapsulation, it's by no way a synonym for encapsulation.

I agree that knowing an underlying class's implementation is useful
(in fact, very useful) but what I'm talking is about should-ness, we
shouldn't _need_ to know the underlying implementation, but if we know
it, it's fine and it's great, since you can do tricks that you
couldn't do otherwise (at your own risks).

No it's not synonym, but one way of encapsulation.

> > (which, in Python is very
> > weakly implemented, which favors flexibility in many cases[1]).
>
> > [1] In Python, it is impossible to create a completely private
> > variable, which is the reason why the mental model of these other
> > languages doesn't fit Python.
>
> Never heard about the infamous '#define private public' hack in C++ ?
> And don't worry, there are also ways to get at so called 'private' vars
> in Java.

No, but it's violating the language's rule. Python OTOH, provides
formal ways to got to private vars.

> >> In any non-trivial piece of C++ code, and unless the author either used
> >> the explicit 'this' reference or the 'm_xxx' naming convention, you'll
> >> have hard time figuring out where a given name comes from when browsing
> >> a function's code.
>
> > If you're used to the implicit naming scheme it's easy to know where a
> > variable came from, if not the current scope, it's the class' scope
>
> You forgot the global scope.

How many global variables do you have in your projects on average? If
you always have a pageful list of globals in your projects, then you
should consider unlearning and relearning the basic programming
concepts. It's easy to keep track of globals, as you shouldn't have a
lot of them even in a huge project.

> > As a final note:
> > I don't think implicit class reference is superior to explicit class
> > reference, neither
>
> ...

I'm sure you don't believe it since I'm talking on implicit's side,
but that's the fact, I just pointed you out that implicits do have its
positive side (even if you don't consider them positive in _your_
book) but that doesn't meant I believe it is better than the other.

To clear things up:
As a final note:
I don't think implicit class reference is superior to explicit class
reference, but I don't think the vice versa is true either.

I consider they have their own positive and negative sides and
different languages have different "better" definition, for Python it
is explicit, for C/Java/Basic it's implicit.




More information about the Python-list mailing list