In C++ you can disable a function in parent's class by declaring it as private in the child class. How can this be done in Python? I.E. How can I hide parent's function from child's public interface?
+1
A:
class X(object):
def some_function(self):
do_some_stuff()
class Y(object):
some_function = None
This may lead to some nasty and hard to find exceptions being thrown though, so you might try this:
class X(object):
def some_function(self):
do_some_stuff()
class Y(object):
def some_function(self):
raise NotImplementedError("function some_function not implemented")
Jason Baker
2008-10-23 22:49:22
+9
A:
There really aren't any true "private" attributes or methods in Python. One thing you can do is simply override the method you don't want in the subclass, and raise an exception:
>>> class Foo( object ):
... def foo( self ):
... print 'FOO!'
...
>>> class Bar( Foo ):
... def foo( self ):
... raise AttributeError( "'Bar' object has no attribute 'foo'" )
...
>>> b = Bar()
>>> b.foo()
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
File "<interactive input>", line 3, in foo
AttributeError: 'Bar' object has no attribute 'foo'
kurosch
2008-10-23 22:52:51
>There really aren't any true "private" attributes or methods in Python.That is why I didn't ask how to make them private, but how to 'remove' them from the interface. Hope that the edited version is more accurate
bgbg
2008-10-23 23:03:46
I agree that NotImplementedError is probably the best one to use, but if you really wanted to match not having the inherited method at all, raise AttributeError instead (which is what you'd get if the parent method didn't exist).
Tony Meyer
2008-10-24 10:37:19
Good point regarding AttributeError. I will update my example.
kurosch
2008-10-24 15:37:58
This doesn't do what you want -- an AttributeError will only be raised if the foo method is /invoked/ -- getattr(b, 'foo') still returns a method object (an attribute!).
cdleary
2008-10-24 23:39:09
+4
A:
kurosch's method of solving the problem isn't quite correct, because you can still use b.foo
without getting an AttributeError
. If you don't invoke the function, no error occurs. Here are two ways that I can think to do this:
import doctest
class Foo(object):
"""
>>> Foo().foo()
foo
"""
def foo(self): print 'foo'
def fu(self): print 'fu'
class Bar(object):
"""
>>> b = Bar()
>>> b.foo()
Traceback (most recent call last):
...
AttributeError
>>> hasattr(b, 'foo')
False
>>> hasattr(b, 'fu')
True
"""
def __init__(self): self._wrapped = Foo()
def __getattr__(self, attr_name):
if attr_name == 'foo': raise AttributeError
return getattr(self._wrapped, attr_name)
class Baz(Foo):
"""
>>> b = Baz()
>>> b.foo() # doctest: +ELLIPSIS
Traceback (most recent call last):
...
AttributeError...
>>> hasattr(b, 'foo')
False
>>> hasattr(b, 'fu')
True
"""
foo = property()
if __name__ == '__main__':
doctest.testmod()
Bar uses the "wrap" pattern to restrict access to the wrapped object. Martelli has a good talk dealing with this. Baz uses the property built-in to implement the descriptor protocol for the attribute to override.
cdleary
2008-10-25 00:05:19
Well, sure, in my answer it's still "visible", but you can't "use" it per se because it will raise the exception. A valid point, though.
kurosch
2008-10-27 20:53:37