Calling private parent class method from parent class (django) - python

I want to call a redefined private method from an abstract parent class. I am using django if that matters.
class Parent(models.Model):
def method1(self):
#do somthing
self.__method2()
def method2(self):
pass # I also tried calling up a prent method with super
class child(Parent):
def method1(self)
super(Child, self).method1()
def __method2(self):
#do something
I get a
AttributeError: "'Chil' object has no attribute '_Parent__method2'"
What I am doing wrong ?

Initial double underscores prevent polymorphism since both the method definition and the method call get mangled, to two different names. Replace with a single underscore to fix this.
Also, double underscores are not used for "private" attributes, and you should discard whatever reference told you that they are. They're used for MI disambiguation.

Related

Get python class's namespace parent type

Is it possible to get the the namespace parent, or encapsulating type, of a class?
class base:
class sub:
def __init__(self):
# self is "__main__.extra.sub"
# want to create object of type "__main__.extra" from this
pass
class extra(base):
class sub(base.sub):
pass
o = extra.sub()
The problem in base.sub.__init__ is getting extra from the extra.sub.
The only solutions I can think of at the moment involve having all subclasses of base provide some link to their encapsulating class type or turning the type of self in base.sub.__init__ into a string an manipulating it into a new type string. Both a bit ughly.
It's clearly possible to go the other way, type(self()).sub would give you extra.sub from inside base.sub.__init__ for a extra type object, but how do I do .. instead of .sub ? :)
The real answer is that there is no general way to do this. Python classes are normal objects, but they are created a bit differently. A class does not exist until well after its entire body has been executed. Once a class is created, it can be bound to many different names. The only reference it has to where it was created are the __module__ and __qualname__ attributes, but both of these are mutable.
In practice, it is possible to write your example like this:
class Sub:
def __init__(self):
pass
class Base:
Sub = Sub
Sub.__qualname__ = 'Base.Sub'
class Sub(Sub):
pass
class Extra(Base):
Sub = Sub
Sub.__qualname__ = 'Extra.Sub'
del Sub # Unlink from global namespace
Barring the capitalization, this behaves exactly as your original example. Hopefully this clarifies which code has access to what, and shows that the most robust way to determine the enclosing scope of a class is to explicitly assign it somewhere. You can do this in any number of ways. The trivial way is just to assign it. Going back to your original notation:
class Base:
class Sub:
def __init__(self):
print(self.enclosing)
Base.Sub.enclosing = Base
class Extra(Base):
class Sub(Base.Sub):
pass
Extra.Sub.enclosing = Extra
Notice that since Base does not exist when it body is being executed, the assignment has to happen after the classes are both created. You can bypass this by using a metaclass or a decorator. That will allow you to mess with the namespace before the class object is assigned to a name, making the change more transparent.
class NestedMeta(type):
def __init__(cls, name, bases, namespace):
for name, obj in namespace.items():
if isinstance(obj, type):
obj.enclosing = cls
class Base(metaclass=NestedMeta):
class Sub:
def __init__(self):
print(self.enclosing)
class Extra(Base):
class Sub(Base.Sub):
pass
But this is again somewhat unreliable because not all metaclasses are an instance of type, which takes us back to the first statement in this answer.
In many cases, you can use the __qualname__ and __module__ attributes to get the name of the surrounding class:
import sys
cls = type(o)
getattr(sys.modules[cls.__module__], '.'.join(cls.__qualname__.split('.')[:-1]))
This is a very literal answer to your question. It just shows one way of getting the class in the enclosing scope without addressing the probably design flaws that lead to this being necessary in the first place, or any of the many possible corner cases that this would not cover.

Python metaclass (abc module) inheritance with nested classes

I've written a Python 3 metaclass containing a nested metaclass (with abc), like:
class A_M(object, metaclass=abc.ABCMeta):
class A_nested_M(object, metaclass=abc.ABCMeta):
def ... # some methods
Now, implementing like
class A(A_M):
class A_nested(A_nested_M):
def ...
doesn't work. So, did i miss something about usage of metaclasses or is this type of implementation with nested metaclasses not working at all?
First thing:
Nesting class declarations is of near no use for anything in Python. Unless you are using the nested class hierarchy itself as a hard-coded namespace to keep attributes, you probably are doing the wrong thing already.
You did not tell what your (actual) problem is and what you are trying to achieve there, nor why you are using the ABCmeta metaclass. So it is hard to suggest any actually useful answers - but we can try clarifying some things:
First: you are not writting a metaclass, as you suggest in the text "I've written a Python 3 metaclass containing a nested metaclass..." - you are creating ordinary classes that have the ABCmeta as its metaclass. But you are not creating new metaclasses - You would if you were inheriting from type or from ABCMeta itself - them your new class would be used in the metaclass= parameter of subsequent (ordinary) classes. That is not the case.
Now, second, everything that is defined inside the body of your outermost A_M class will be only "visible" as attributes of A_M itself. That is the source of your error - when you try to inherit from A_nested_M you should actually write:
class A_M(object, metaclass=abc.ABCMeta):
class A_nested_M(object, metaclass=abc.ABCMeta):
def ... # some methods
class A(A_M):
class A_nested(A_M.A_nested_M):
def ...
See - A_M.A_nested_M will make Python find the superclass for A_nested: there is no reference in the local or global namespaces for A_nested_M as it only exists as an attribute of A_M outside the body of the class A_M... statement.
That said, this is still useless. If you want to have instances of A_nested referenced by instances of A class, you have to create these instances inside A.__init__() call - at which point it makes no difference if A_nested is declared inside a class body or at the module level:
class A_M(object, metaclass=abc.ABCMeta):
pass
class A_nested_M(object, metaclass=abc.ABCMeta):
def ... # some methods
class A_nested(A_nested_M):
...
class A(A_M):
def __init__(self):
self.nested = A_nested()
Now, that can be of some use. You can also declare the classes actually nested, but the only way they can be useful is by creating instances of them anyway. And unlike nested functions, nested classes do not have access to attributes or variables declared on the "nesting" class namespace (but for referring to them by their qualified name. I.e. in your example, if the A class would contain a b classmethod, a method inside A_nested that would call this method would have to call A.b(), not b())
You should implement your class like this:
class A(A_M):
class A_nested(A_M.A_nested_M):
def ...
Because A_nested_M is an inner class, you should access it just like you would access any of the class attributes, i.e. A_M.A_nested_M. See this link.

Calling a method from a parent class in Python

Can anyone help me with the correct syntax to call my method __get_except_lines(...) from the parent class?
I have a class with a method as shown below. This particular method has the 2 underscores because I don't want the "user" to use it.
NewPdb(object)
myvar = ...
...
def __init__(self):
...
def __get_except_lines(self,...):
...
In a separate file I have another class that inherits from this class.
from new_pdb import NewPdb
PdbLig(NewPdb):
def __init__(self):
....
self.cont = NewPdb.myvar
self.cont2 = NewPdb.__get_except_lines(...)
And I get an attribute error that really confuses me:
AttributeError: type object 'NewPdb' has no attribute '_PdbLig__get_except_lines'
Your problem is due to Python name mangling for private variable (http://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references). You should write:
NewPdb._NewPdb__get_except_lines(...)
super(<your_class_name>, self).<method_name>(args)
e.g.
super(PdbLig, self).__get_except_lines(...)
The entire point of putting a double underscore in front of a name is to prevent it from being called in a child class. See http://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references
If you want to do this, then don't name it with a double underscore (you can use a single underscore), or create an alias for the name on the base class (thus again defeating the purpose).

How to not accidentally override a method in python?

I know there are a bunch of similar questions out there. But my question is different.
I don't want to make a method which can't be overridden.
I want to protect my newly created class to not accidentally override something.
Using underscore as a prefix is pretty good, but soon I'll get a lot of methods with a lot of underscores. and somewhere in my inherited class, I will override the grand-ancestor's class method.
What I really want is something as simple as this:
class Cat(Mammal):
def walk(self):
if ancestor_has_function('walk'):
parent.walk();
do_something_here();
If any of Cat's ancestor (Either it is Mammal, Animal, or LifeForm) has "walk" method, then the parent method should be executed first.
Is that any possibility to do this in python?
EDIT:
For instance this is the resume of answers I considered as good. Hope this will help others:
class Animal(object):
pass
#def walk(self):
# print('animal walk')
class Mammal(Animal):
def walk(self):
if hasattr(super(Mammal, self), 'walk') and callable(super(Mammal,self).walk):
super(Mammal, self).walk()
print('mammal walk')
class Cat(Mammal):
def walk(self):
super(Cat, self).walk()
print('cat walk')
if __name__ == '__main__':
cat = Cat()
cat.walk()
And here is the output:
mammal walk
cat walk
Try to uncomment Animal's walk method, and you will have it work as well too.
Generally speaking, you'll probably want to provide at least a stub method in whichever superclass is the most generic:
class Mammal(object):
def walk(self):
pass
Then, extend it in subclasses by calling super():
class Cat(Mammal):
def walk(self):
super(Cat, self).walk() # or just super().walk(), in Python 3+
do_something_here()
Making the super() call conditional is not hard, but it's probably a bad idea: it's verbose, fragile, and only encourages bad practices. If you really, really have good reason to do it, you can just use hasattr() on the super object, like you would with any other object:
class Cat(Mammal):
def walk(self):
if hasattr(super(Cat, self), 'walk'):
super(Cat, self).walk()
do_something_here()
You would only want to do this in unusual situations, though, such as subclassing classes from a third-party library where you can't rely on certain methods being present, for some reason.
Yep. hasattr checks if there is an attribute with a specific name.
and callable checks if the specific attribute is callable.
class Mammal(object):
def walk(self):
print "walking"
class Cat(Mammal):
def walk(self):
if hasattr(Mammal,'walk') and callable(Mammal.walk):
Mammal.walk(self);
print "another walking!"
and now:
>>> my_cat = Cat()
>>> my_cat.walk()
walking
another walking!
Note that you can also use super to get your parent class like that:
if hasattr(super(Cat, self),'walk'):
You can use the dir() function to get all the names declared for some module or class. Methods declared in classes higher up in the hierarchy will also be included. Note, however, that this will also include attributes, so check with callable() first.
Also, calling the parent method looks a bit different in python, see the code below.
def walk(self):
if "walk" in dir(Mammal) and callable(Mammal.walk):
Mammal.walk(self)
# do something
you can keep your original method in a field
class MyClass:
def __method(self):
pass
def __init__(self):
self.method = __method
and than check for identity and call the saved method
import inspect
class SomeClass():
def __init__(self):
...
def somefunc(self):
....
def someOtherFunc(self):
....
allmembers = inspect.getmembers(SomeClass, predicate=inspect.ismethod)
getmembers returns a list of all methods define within the given class, it is a list of tuples that contains method names and definitions:
[('__init__', <unbound method SomeClass.__init__>),
('somefunc', <unbound method SomeClass.somefunc>),
('someOtherFunc', <unbound method SomeClass.someOtherFunc>)]
Since first elements of the tuple are strings, you can use string based methods to filter base methods like __init__
allmembers = filter(lambda x: not x.startswith('__'), [x[0] for x in inspect.getmembers(SomeClass, predicate=inspect.ismethod))])
[('somefunc', <unbound method SomeClass.somefunc>),
('someOtherFunc', <unbound method SomeClass.someOtherFunc>)]
You can get a list of all methods defined within the class and check if you have a similarly named method, Sincegetmembers returns you an unbound method instance, you can also reach that function easily.

Python naming conventions for attributes and methods meant to be overwritten

I have some object oriented code in Python, where some classes are meant to be extended to provide the missing custom bits of code (a la Template Method pattern, but also with variables), that will only be used by the super class, not by the client code using them.
Are there any style conventions for such abstract (or dull, because their implementation in the super class would be either pass or raise a NonImplemented exception) methods and attributes?
I've been browsing the PEP-0008 and it only mentions about prepending an underscore to private members not intended to be used by subclasses.
I usually use single underscore e.g. _myvar for protected (as in C++) methods/attributes, which can be used by derived classes and use double underscore e.g. __var when it should not be used by anybody else, and as double-underscore names at class definition level are mangled, so they can't be overridden in derived class e.g.
class A(object):
def result1(self): # public method
return self._calc1()
def result2(self): # public method
return self.__calc2()
def _calc1(self): # protected method, can be overridden in derived class
return 'a1'
def __calc2(self): # private can't be overridden
return 'a2'
class B(A):
def _calc1(self):
return 'b1'
def __calc2(self):
return 'b2'
a = A()
print a.result1(),a.result2()
b = B()
print b.result1(),b.result2()
Here it seems derived class B is overriding both _calc1 and __calc2 but __calc2 isn't overridden because its name is already mangled with class name and hence output is
a1 a2
b1 a2
instead of
a1 a2
b1 b2
but ultimately choose any convention and document it, also in above case it is not that base class can't override private, here is a way :)
class B(A):
def _calc1(self):
return 'b1'
def _A__calc2(self):
return 'b2'
First of all i think that you are mistaken when you say that:
about prepending underscore to private members not intended to be used by subclasses.
Actually prepending a method/attribute by underscore is a python convention that mean that this method/attribute shouldn't be accessed outside the class (and its subclass) and I think you forgot to read about the double underscore that is used to make a method/attribute not possible to override.
class Foo(object):
def __foo(self):
print "foo"
def main(self):
self.__foo()
class Bar(Foo):
def __foo(self):
print "bar"
bar = Bar()
bar.main()
# This will print "foo" and not "bar".
There is another way of declaring stub method by the way which is using abc.ABCMeta and abc.abstractmethod.
There isn't really a naming convention for these methods because they'll have the same name when they're overridden. Otherwise they wouldn't be overridden! I think having the method to be overridden do something trivial, and documenting it accordingly, is good enough:
class MyClass:
def aMethod():
'''Will be overridden in MyDerivedClass'''
pass
Name mangling, which you mention in your question, is useful if you have a non-trivial method that will be overridden, but you still want to be able to access the base version. See the documentation for more info and an example.

Categories