inner classes in python as inner classes in Java

C

Carlo v. Dango

Inner classes in Python is merely hidding of structure rather than
providing a scope as in Java. eg. this program fails in the print-line..


class A(object):
def __init__(self):
self.name = "hans"

class B(object):
def foo(self):
print "my name is " , self.name
a = A()
b = a.B()
b.foo()


to remedy this, I thought of having an "outer" attribute which was
accessed when the class itself could not find a given property. However, I
think the following definition is problematic as it bites itself. in the
init method i introduce the "outer" field.. however, at this point the
__getattr__ is called which makes me look in the outer scope.. which was
not the intention. How to do a proper implementation?


class A(object):
def __init__(self):
self.name = "hans"

class B(object):
def __init__(self, outer=None):
self.outer = outer

def foo(self):
print "my name is " , self.name

def __getattr__(self, name):
if self.outer != None:
return self.outer.getattr(name)
else: raise Error("attribute ", name, " not found!")

def __setattr__(self, name, value):
if self.outer != None:
self.outer.setattr(name, value)
else: raise Error("attribute ", name, " not found!")

a = A()
b = a.B(a)
b.foo()




Carlo...
 
A

Alex Martelli

Carlo v. Dango wrote:
...
init method i introduce the "outer" field.. however, at this point the
__getattr__ is called which makes me look in the outer scope.. which was
not the intention. How to do a proper implementation?

I think what's called is __setattr__, NOT __getattr__. __setattr__ if you
define it is called for EVERY attribute you set by assignment, and there
is no "finding" involved whatsoever. Do you TRULY want to delegate all
attribute settings, performed on an instance of the innerclass, to the
corresponding 'outer' -- _except_ self.outer? If so, then the following
should be OK:

class B(object):

def __init__(self, outer=None):
# the key issue: bypass B.__setattr__ by delegating to the
# superclass's (object's) implementation
object.__setattr__(self, 'outer', outer)

def foo(self):
print 'my name is', self.name

def __getattr__(self, name):
if self.outer is None:
raise AttributeError, name
return getattr(self.outer, name)

def __setattr__(self, name, value):
if self.outer is None:
raise AttributeError, name
return setattr(self.outer, name, value)

I have taken the occasion to correct other errors you had with
attribute getting and setting, and indent with spaces, not with
tabs (your post was indented with tabs thus unreadable with such
newsreaders as KDE's KNode, Outlook Express, et al: please do
NOT post code indented with tabs, thanks).

It's not very clear to me what you mean to obtain with this
class B, but, in any case, this is how to do this kind of
automatic delegation in Python.


Alex
 
C

Carlo v. Dango

Do you TRULY want to delegate all
attribute settings, performed on an instance of the innerclass, to the
corresponding 'outer' -- _except_ self.outer?

No, what a strange idea ;-) All attributes not found in the class should
be forwarded to it's outer instance (as I want to simulate that the inner
class instance is within the scope of its outer class instance.
tabs (your post was indented with tabs thus unreadable with such
newsreaders as KDE's KNode, Outlook Express, et al: please do
NOT post code indented with tabs, thanks).

why is that? has TAB-technology not reached linux yet? :) I try to
remember it, I just prefer tabs over spaces..

class B, but, in any case, this is how to do this kind of
automatic delegation in Python.

actually its forwarding or consultation, as self is re-bound when you
invoke the outer..


<- carlo ->
 
C

Carlo v. Dango

Comming to think of it, it can't be done in python! Since there is no way
to denote you want to access a field rather than creating a new one,
__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?

<- carlo ->
 
A

Alex Martelli

Carlo said:
No, what a strange idea ;-) All attributes not found in the class should
be forwarded to it's outer instance (as I want to simulate that the inner
class instance is within the scope of its outer class instance.

What does "found" have to do with attribute setting? In Python:

class X: pass

x=X()
x.foo=23

sets attribute named 'foo' to the value of 23 on x. "found"...?! What
can you possibly mean?

You'll have to decide what semantics you want to obtain when an
attribute is set on an instance of the "inner class" -- I sure can't do
it on your behalf.

why is that? has TAB-technology not reached linux yet? :) I try to
remember it, I just prefer tabs over spaces..

There's a reason the official Python style guidelines have been
amended to prefer spaces instead of tabs, you know. Sure, there
will be some programs who display tabs in a way compatible with
your preferences, but others won't; be conservative in what you
generate -- spaces are ensured to be displayed as you intend, tabs
are NOT, so don't use the latter in any code you send to others.

actually its forwarding or consultation, as self is re-bound when you
invoke the outer..

In your Python code (and mine), it is false that "self is re-bound"
(only an instruction such as "self = ..." would do that, and there is
no such instruction in that code). Sure, when a method A of
object B calls a method X of object Y, the local name 'self' is
bound to Y in the execution of X while the same name is bound
to B in the execution of A. But that is not re-binding -- just the
distinction between lexically-same names in different scopes.

Anyway, the term "delegation" is common for the operation in
question - it is for example used in the "gang of 4"'s Design
Pattern book.


Alex
 
A

Alex Martelli

Carlo said:
Comming to think of it, it can't be done in python! Since there is no way
to denote you want to access a field rather than creating a new one,

When you access a field you access it, e.g:

print blah.bluh

this accesses it -- it will never create anything. When you ASSIGN to a
field you create it if it wasn't there (if it was there, the previous value
is removed, and the field is created afresh again). You can use
descriptors (in new-style classes) to handle assignments (and accesses
too, if you want) in special ways for some attributes.

__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.

For the case of someobject.attr = value, you do get to add complications
if you want -- e.g., when wrapping someobject in your proxy, you can
introspect to find what attributes it had at that time, and prepare a
custom class with the set of descriptors you want. Or, if you are in no
hurry, you can to such checks at the time of eahc assignment.

Such tender loving care will typically break the semantics of your
proxying in general cases, but if you have total control on the class
whose instances you're wrapping that need not be the case. It's
still hard to say what benefits you'll be getting, of course, but there
may be some cunning plan behind it all.


Alex
 
C

Carlo v. Dango

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..


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()
 
C

Carlo v. Dango

You'll have to decide what semantics you want to obtain when an
attribute is set on an instance of the "inner class" -- I sure can't do
it on your behalf.

I want the semantics of java's inner classes and the semantics of inner
methods... that the inner class shares the fields and methods of its outer
class instance.. But I've come to realize I can't do this in python, as
the statement in some method in the inner class "self.i = 42" can be
interpreted as "create i in the inner class instance" or "lookup i in the
'outer scope' and set it"


There's a reason the official Python style guidelines have been
amended to prefer spaces instead of tabs, you know. Sure, there
will be some programs who display tabs in a way compatible with
your preferences, but others won't; be conservative in what you
generate -- spaces are ensured to be displayed as you intend, tabs
are NOT, so don't use the latter in any code you send to others.

hmm depends on which font people are using.. if it's not monospace, the
layout will also change.. I doubt that there are many news readers where
you cannot set TAB == 4 spaces



In your Python code (and mine), it is false that "self is re-bound"
(only an instruction such as "self = ..." would do that, and there is
no such instruction in that code). Sure, when a method A of
object B calls a method X of object Y, the local name 'self' is
bound to Y in the execution of X while the same name is bound
to B in the execution of A. But that is not re-binding -- just the
distinction between lexically-same names in different scopes.

well, I disagree... there is a difference between virtual and non-virtual
methods. The first does not re-bind self, when doing super calls or when
casting an object to some super class and invoking methods on it (like
using C++'s :: )

Anyway, the term "delegation" is common for the operation in
question - it is for example used in the "gang of 4"'s Design
Pattern book.

well, 'delegation' is cited in OOPSLA, ECOOP, AOSD etc litterature of
being defined in the seminal 1986 OOPSLA paper "Using Prototypical Objects
to Implement Shared Behavior in Object-Oriented Systems" by H. Lieberman.
the GOF book came out around 9 years later.


Carlo
 
D

Duncan Booth

I want the semantics of java's inner classes and the semantics of
inner methods... that the inner class shares the fields and methods of
its outer class instance.. But I've come to realize I can't do this in
python, as the statement in some method in the inner class "self.i =
42" can be interpreted as "create i in the inner class instance" or
"lookup i in the 'outer scope' and set it"

What you want wouldn't necessarily be impossible. You should be able to
create a metaclass for the inner class that automatically creates
properties in the inner class which access the outer class fields. That way
you could expand:

self.a = 42

to something equivalent to:

self.__outer.a = 42

Actually, thinking about it you need to put the metaclass on the outer
class rather than the inner one. That way when the outer class is created,
you can check its dictionary for any classes it contains and give each of
those classes the appropriate properties.

I think it ought also to be possible to add a __get__ method to the inner
class so that accessing the inner class through an instance of the outer
class returns what would effectively be a 'bound class' (cf bound method)
which sets the __outer member automatically when you create an instance of
the inner class.
 
A

Alex Martelli

Carlo said:
I want the semantics of java's inner classes and the semantics of inner
methods... that the inner class shares the fields and methods of its outer
class instance.. But I've come to realize I can't do this in python, as

I don't understand what you mean. "inner methods" (? presumably you
mean nested functions ?) cannot re-bind names in outer scope -- you say
you want these semantics, and you also seem to say you DO want assignments
on the innerobject's attribute to re-bind attributes on the outer. There
is a contradiction here in what you say. Neither in Python nor with any
other tools whatsoever can you implement contradictory requirements.

Give non-contradictory requirements about what you want to happen
upon "inner.i = 23" and you will be able to implement them (whether
they will be at all useful or sensible is quite another issue, of
course).
the statement in some method in the inner class "self.i = 42" can be
interpreted as "create i in the inner class instance" or "lookup i in the
'outer scope' and set it"

It can be interpreted to mean any non-contradictory set of requirements
you want to be interpreted as. Having as yet no idea of what you may
hope to accomplish, that is useful at all, I can't guess what those
hypothetical requirements could possibly be.

hmm depends on which font people are using.. if it's not monospace, the
layout will also change..

This assertion is false. Since the _significant_ whitespace is only
that which occurs at the start of a line, as long as each occurrence
of a space character is displayed with the same width X, it cannot
possibly matter in terms of code meaning what witdths x1, x2, ... xN
are used to display other, non-whitespace characters. In particular
it cannot matter whether x1==x2==...==xN or not, nor whether any one,
several or all xi's happen to equal X.

If you want your code's meaning to be unaltered, always indent it
with spaces, NOT tabs. It does NOT matter which fonts people are
using. If you indent with spaces, they'll see your code meaning
the same thing. If you indent with tabs, there's no guarantee. This
is part of the reason PEP 8, "Style Guide for Python Code", was
updated by Guido van Rossum to read "For new projects, spaces-only
are strongly recommended over tabs" and similar phrasings.
I doubt that there are many news readers where
you cannot set TAB == 4 spaces

Two might suffice, when they're among the most widely used: Microsoft
Outlook Express, and KDE's KNode. And no, of course I'm not going to
change my favourite newsreader to accomodate people who choose to
violate the official Python style guide.

well, I disagree... there is a difference between virtual and non-virtual
methods.

Not in Python: absolutely no difference, since there's no such thing
as a "non-virtual" method.
The first does not re-bind self, when doing super calls or when
casting an object to some super class and invoking methods on it (like
using C++'s :: )

There is no "casting" in Python. If you refer to such notation as, e.g.:

class mydict(dict):
def __getitem__(self, key):
return dict(self)[key]

I'll inform you that the dict(self) DOES return an object with an id
different from that of self, which would mean (if dict were coded in
Python) that the 'self' received by the superclass's __getitem__ would
be a different one from that in the subclass. That is different from
the "superclass call" usage
return dict.__getitem__(self, key)
where an _unbound_ method is extracted from class dict, exactly in
order to be able to pass to it an 'unmodified' self explicitly (the
main advantage being one of efficiency).

well, 'delegation' is cited in OOPSLA, ECOOP, AOSD etc litterature of
being defined in the seminal 1986 OOPSLA paper "Using Prototypical Objects
to Implement Shared Behavior in Object-Oriented Systems" by H. Lieberman.
the GOF book came out around 9 years later.

....and became an instant best-seller, cementing the usage. So, e.g., a
proxy is equally well said to provide _delegation_ to an object it proxies
for, as to provide _forwarding_ to that object. Yes, I know Szyperski tries
to draw a fine distinction -- that "subsequently delegated messages are
dispatched back to the original delegator", which isn't true in forwarding
(the difference would appear in cases of what the gang of 4 call the
'Template Method' design pattern). What I'm saying is that this terminology
distinction has little practicel currency -- look, for example, at what C#
calls 'delegates' and tell me how delegating to them could `dispatch back`
to the delegator (caller) [answer: it won't]. Or see how Fowler uses the
terms in his "Refactoring" for the "Replace Delegation with Inheritance"
and "Replace Inheritance with Delegation" refactorings (p. 325 ff).


Alex
 
G

Gonçalo Rodrigues

[text snipped]
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()

What do you *really* want? As far as I remember (it's been a long time
since I've dealt with Java), the biggest use for inner classes in Java
is in faking closures. That's a non-issue in Python, in part because
*every* object is a first class citizen, functions, methods and
classes included. There is no such thing as a class-scope, only
function definitions open a new (local) scope. As others have posted
you *can* fake that with __setattr__ and/or a metaclass solution, but
*why* would you want to go down that path that is what I cannot
fathom.

With my best regards,
G. Rodrigues
 
A

Alex Martelli

Carlo said:
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).

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
 
D

Daniel Dittmar

Alex said:
I don't understand what you mean. "inner methods" (? presumably you
mean nested functions ?) cannot re-bind names in outer scope -- you
say you want these semantics, and you also seem to say you DO want
assignments on the innerobject's attribute to re-bind attributes on
the outer. There is a contradiction here in what you say. Neither
in Python nor with any other tools whatsoever can you implement
contradictory requirements.

Inner classes (not static inner classes) in Java work as follows:
- the inner class has a reference to an object of the enclosing class
- any identifier is searched in the method scope, the inner class scope, the
enclosing class scope, so an identifier A can mean A (local), this.A
(inner), this.__enclosing__.A (enclosing), depending on where the compiler
finds it.

A Python implementation for inner classes would be:
class Inner:
def __init__ (self, enclosing):
self.__enclosing__ = enclosing

def __getattr__ (self, name):
return getattr (self.__enclosing__, name)

def __setattr__ (self, name, value):
if hasattr (self.__enclosing__):
setattr (self.__enclosing__, name, value)
else:
setattr (self, name, value)

Java hides the 'enclosing' when creating objects, so
new Inner ()
becomes
new Inner (this)

Not that I think that hiding the real access path is a good idea.

Daniel
 
C

Carlo v. Dango

What you want wouldn't necessarily be impossible. You should be able to
create a metaclass for the inner class that automatically creates
properties in the inner class which access the outer class fields. That
way
you could expand:

self.a = 42

to something equivalent to:

self.__outer.a = 42

Actually, thinking about it you need to put the metaclass on the outer
class rather than the inner one. That way when the outer class is
created,
you can check its dictionary for any classes it contains and give each of
those classes the appropriate properties.

that is a nice idea, however, how do I know which fields are defined in
the outer class?? fields can be defined in every method and on runtime..

class A(object):
def foo(self, arg):
if arg == 0:
self.i = 3 # create a 'i'
else
self.j = 4 # create a 'j'


so when the metaclass examines my A class, are both i and j defined in the
class or how?


I think it ought also to be possible to add a __get__ method to the inner
class so that accessing the inner class through an instance of the outer
class returns what would effectively be a 'bound class' (cf bound method)
which sets the __outer member automatically when you create an instance
of
the inner class.

that would be rather cool, but Im not sure I fully understand your idea.
could you produce some (pseudo) code?


-carlo
 
A

Alex Martelli

Carlo v. Dango wrote:
...
that is a nice idea, however, how do I know which fields are defined in
the outer class?? fields can be defined in every method and on runtime..

You can check if class A has [at this very moment] an attribute named 'x' by
hasattr(A, 'x').

More likely, you will be interested in whether some INSTANCE a of class A
has that attribute [at this very moment], i.e. hasattr(a, 'x').

You can of course only check the situation "at this very moment", not if a
will at some future point during its lifetime acquire or lose such an
attribute (that cannot, in general, be forecast).

Given that your purpose is to set (i.e., bind or rebind) an attribute 'x'
either on a or on some other object b, I cannot see any usefulness in
making that decision based on whether a had that attribute now or had
it at some time in the past. I have repeatedly asked you to show a use
case where dispatching attribute-setting in such ways serves a purpose
useful to the application program, but received no usable answer. This
reinforces my current working hypothesis that whatever purpose you
think you need to serve this way might likely be best served otherwise,
but, without knowing of that purpose, I cannot advance further suggestions.

E.g., you've repeatedly mentioned some analogy to inner functions - which
CANNOT re-bind names in their outer scope! -- thus failing to provide any
usefulness whatsoever in understanding your perceived binding needs...!

If and when the purpose that's supposed to be served by such dispatching
is made clear, THEN mechanisms to achieve such dispatching may be
meaningfully discussed, compared, and contrasted; not before.


Alex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top