inner classes in python as inner classes in Java
Alex Martelli
aleax at aleax.it
Thu Oct 16 11:15:00 EDT 2003
More information about the Python-list mailing list
Thu Oct 16 11:15:00 EDT 2003
- Previous message (by thread): inner classes in python as inner classes in Java
- Next message (by thread): inner classes in python as inner classes in Java
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Carlo v. Dango wrote: > On Wed, 15 Oct 2003 22:20:44 GMT, Alex Martelli <aleaxit at yahoo.com> wrote: > >>> __setattr__ will have no changes of knowing when to create the field or >>> look it up in the outer scope... this suxx man... I never understood the >>> smart thing about that feature in python.. anyone care to enlighten me? >> >> If you can't see that it's simpler to let >> >> target = value >> >> have the same semantics whether target was already bound to something >> or not, it's hard to see what will convince you. > > I can't... mispelling occours and leed to stupid bugs rather than compile > errors which are simple to check. Even smalltalk has this feature.. So does pychecker, e.g., given the following erroneous a.py: def func(lead): "return the argument if true, else 23" if not lead: leed = 23 return lead running "pychecker a" will easily warn you: a.py:4: Local variable (leed) not used et voila, the "stupid bug" is squashed, without any need to burden down the language with ``declarations'' for the purpose. Some of pychecker's functionality is likely to get incorporated in future versions of Python interpreter (just like good old tabnanny.py's functionality was once incorporated via the -t switch). >> its still hard to say what benefits you'll be getting, of course, but >> there may be some cunning plan behind it all. > > aaaah come on :) you really cannot see the nice things of having a scope > for inner class instances?? It's like inner method.. atleast they share > scope with their outer method... if it didn't it would render inner > methods almost useless.. > > class A(object): > def foo(self): > i = 3 > def bar(): > print i > > bar() Your stubborn refusal to follow Python's recommended style, which I already repeatedly explained to you (indent with spaces, not tabs) makes your code look like the above -- flat and meaningless -- in KDE's KNode (and MS Outlook Express, too, also widely used). In any case, I cannot see any _usefulness_ whatsoever in the above snippet, no matter how one inserts whitespace in it -- it appears to use a def statement for 'bar' in a totally gratuitous way, without any benefit whatsoever. There ARE, of course, good use cases for nested functions (the inner one just isn't a method no matter how much you waste your breath saying it is); many of them relate to returning the function object created by the inner def (the 'closure' idiom): def make_summator(addend): def summator(augend): return augend + addend return summator this is about the simplest case that is of any use. When Python did not nest scopes, this was equivalently implemented as: def make_summator(addend): def summator(augend, addend=addend): return augend + addend return summator and you can still code it that way (it's marginally faster at runtime, but not enough to matter). It's fractionally handier to not have to inject names explicitly, but, again, it's hardly a major issue in terms of programmer's productivity. A simple but non-toy use case for a class defined within another class might be an iterable/iterator pair: class tree(object): # snipped: most definitions of tree's methods def __getitem__(self, tree_index): # somehow locate and return the item of this tree # corresponding to key 'tree_index', or raise # IndexError if tree_index is out of bounds class iterator(object): def __init__(self, tree): self.tree = tree self.index = 0 # or whatever means "first item's index" def __iter__(self): return self def next(self): try: item = self.tree[self.index] except IndexError: raise StopIteration self.index += 1 # or whatever means "next item's index" return item def __iter__(self): return self.iterator(self) Note the amount of 'overhead' you have here to let the tree's __iter__ method specifically pass 'self' when instantiating the tree_iterator class: essentially negligible when compared to the amount of other code in even such a simple example as this one. In contrast, a closure might want to bind some number of names from the outer scope, and the amount of other code involved can be tiny, so the admittedly-small overhead of explicitly injecting (binding) names stands out more. At the same time, having tree.iterator intrinsically "inherit" names from the scope of class tree would be potentiallly quite problematic: e.g. the user might erronously 'index' an iterator and be in fact indexing the whole tree (if name __getitem__ got thus transparently injected), quite ignoring the current index in the iterator. The incredibly tiny benefits of having a class automatically get names from the scope of the containing class would obviously be dwarfed by the evident problems. Further note that neither in nested functions, neither in nested classes, is there any need in the above examples to BIND any name in the containing scope. Indeed, nested functions just don't support that: the inner function can ACCESS outer names, but NOT rebind them. The interest of binding outer names WOULD be there -- in examples not quite as trivial as these, but almost -- but there is absolutely no interest in having that be 'transparent'. There is currently no syntax to rebind names from an inner function in the outer scope (you need to achieve similar ends by _mutating_ mutable objects in the outer scope, a very different concept from that of rebinding names). Rebinding names from the inner to the outer class is achieved in just the same way as accessing them -- i.e. normally by explicit non-transparent syntax such as self.tree.foobar (be it for access or for rebinding). But what is the purported usefulness of having the inner class act as a somewhat transparent proxy for the outer one? The iterable/iterator example does nothing of the kind and has no need for any such transparency (which indeed would seriously impair it). What are the use cases for instances of the nested (inner) class acting as proxies for instances of the containing (outer) one, intercepting some but not all of the attribute rebindings (and presumably deletions? have not seen you implement __delattr__ for that purpose) yet handling other rebindings "on its own", AND somehow choosing which re-bindings to delegate and which to intercept in a totally automatic/introspective way (e.g. based on what set of attributes happen to be defined on the outer class's instance at some given point in time)? As I said, there may be some cunning plan behind this weird kind of specs, but you surely have not given any indication of what need you might have for them (indeed, haven't given any complete non-contradictory set of specs that I've seen for the rebinding behavior you appear to desire). And no, I "cannot see the nice things" unless you indicate a use case: I have neither had nor seen such a specific need in 4 years of Python usage, writing, teaching, mentoring, tutoring, and consulting. I _have_ used inner classes in Java, mostly as workarounds for the lack of multiple inheritance (a lack which Python doesn't share), but also marginally for other things -- but none that would require transparent rebinding in a Python setting. If you _do_ finally deign to indicate the use cases you have in mind, as well as the exact, precise and non-contradictory semantics for attribute access and for attribute rebinding that you think are best suited to handle your use cases, it's possible that experienced Pythonistas may be able to indicate preferable approaches, as well as to advise on how to implement the approach you think you need. Alex
- Previous message (by thread): inner classes in python as inner classes in Java
- Next message (by thread): inner classes in python as inner classes in Java
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Python-list mailing list