Hi I have a simple Inheritance example in Python.
class Person:
def __init__(self,name):
self.name=name
self.name0=name[0]
self.name1=name[1]
self.lastchar=self.returnSomechar()
def returnfirstchar(self):
return self.name[0]
def returnSomechar(self):
self.p=self.name1
return self.p
class Employee(Person):
def returnfirstchar(self):
""" I dont implement at all"""
def returnSomechar(self):
a='Lawson'
b='Jack'
self.p=self.name1+a+b
#
return super(Employee,self).returnSomechar()
e=Employee('David')
e.returnSomechar()
This returned 'a'
I expected the child class self.p to get passed and result would be David Lawson Jack
Cleary In child class super() didnt use the self.p of child class rather it used self.p of base class.
can you please help where i am missing
Thanks
Related
Here is an example in easy form what I am trying to achieve.
class Parent:
def abc():
pass
class Child(Parent):
def pqr():
pass
Child.abc
<function Parent.abc()>
Child.abc.__qualname__
'Parent.abc'
figure_out_class_from_class_func(class_func):
...
derive class from class_func.__qualname__
return class
figure_out_class_from_class_func(Child.abc) returns -> Parent.
Actually I want it to return Child as actually I am passing Child class.
So basically __qualname__ is not my friend here. Is it anyhow possible to figure out actual class rather than the parent class(where function is implemented) using Class.function ?
EDIT:
bit better example:
class Parent():
def __init__(self):
print(self.x)
def parent_func1(self):
pass
class Child(Parent):
x=1
def __init__(self):
print(self.x)
def child_func1(self):
pass
def special_function(class_func):
func_module = inspect.getmodule(class_func)
class_name = getattr(class_func, "__qualname__", None).split(".")[0]
class_obj = getattr(func_module, class_name)
class_obj()
Now calling special_function(Child.child_func1) is fine-> print 1
But special_function(Child.parent_func1) gives error:
ERROR:root:Internal Python error in the inspect module.
Below is the traceback from this internal error.
1 class Parent():
2 def __init__(self):
----> 3 print(self.x)
4 def parent_func1(self):
5 pass
AttributeError: 'Parent' object has no attribute 'x'
Is there any way to find out that I have called Child.parent_funcn through Child but not through Parent ?
I have googled around for some time, but what I got is all about INSTANCE property rather than CLASS property.
For example, this is the most-voted answer for question from stackoverflow
class C(ABC):
#property
#abstractmethod
def my_abstract_property(self):
return 'someValue'
class D(C)
def my_abstract_property(self):
return 'aValue'
class E(c)
# I expect the subclass should have this assignment,
# but how to enforce this?
my_abstract_property = 'aValue'
However, that is the INSTANCE PROPERTY case, not my CLASS PROPERTY case. In other words, calling
D.my_abstract_property will return something like <unbound method D.my_abstract_property>. Returning 'aValue' is what I expected, like class E.
Based on your example and comment to my previous reply, I've structured the following which works with ABC. :
from abc import ABC
class C(ABC):
_myprop = None
def __init__(self):
assert self._myprop, "class._myprop should be set"
#property
def myprop(self):
return self._myprop
class D(C):
_myprop = None
def __init__(self):
super().__init__()
class E(C):
_myprop = 'e'
def __init__(self):
super().__init__()
e = E()
print(e.myprop)
d = D()
print(d.myprop)
You are correct that there is no Python pre-scan that will detect another developer has not assigned a value to a class variable before initializing. The initializer will take care of notifying pretty quickly in usage.
You can use #classmethod decorator.
I come up with a tricky workaround.
class C(object):
myProp = None
def __init__(self):
assert self.myProp, 'you should set class property "name"'
class D(C):
def __init__(self):
C.__init__(self)
class E(C):
myProp = 'e'
def __init__(self):
C.__init__(self)
print(D.myProp)
print(E.myProp)
But it still has some problems:
D.myProp will not raise any exception to warn the developer about the constraint (assigning myProp as its class property), until the developer initialize an instance of his class.
abc module cannot work with this solution, which means loss of lots of useful features of that module
When I derive a class in Python, I need to call the Base.__init__(self) from the derived __init__(self) function like
class Base(object):
def __init__(self):
pass
class Der(Base):
def __init__(self) :
Base.__init__(self)
Do I need to do the same for __new__(self) and __del__(self) functions like
class Base(object):
def __new__(self):
pass
def __init__(self):
pass
def __del__(self) :
pass
class Der(Base):
def __new__(self):
Base.__new__(self)
def __init__(self) :
Base.__init__(self)
def __del__(self) :
Base.__del__(self)
I am wondering because nothing seems to go WRONG if I don't do that.
I am sure that python gc will take care, but is there anything I need to be worried about if I don't call them from Derived chain
The usage of __init__() and __del() is straightforward but not the __new()__
Since __new()__ returns an instance of the class, we need to call super().__new()__ till the object chain as given below
class Base(object):
def __new__(self):
return super().__new__(self)
class Derive(Base):
def __new__(self):
return super().__new__(self);
The __del()__ can be using similar to __init()__, calling Base.__del()__ is not mandatory unless and until some cleanup is required in base __del() function.
The correct way of writing the code asked in the question is
class Base(object):
def __new__(self):
return super().__new__(self)
def __init__(self):
self.Value = 200
def __del__(self):
pass
class Derive(Base):
def __new__(self):
return super().__new__(self);
def __init__(self):
Base.__init__(self)
def __del__(self):
Base.__del__(self)
It's always better not to implement __new()__ and __del()__ unless we really need it
For example:
class parent(self):
def __init__(self, i):
self.i = i
def something(self, value):
a = child(value)
return a
class child(parent):
def something_that_is_not_init(self):
return self.i
The child class inherits init from the parent class. So my question is, in my parent class, can I create an instance of the child object, use and return it?
I would execute it as following:
a = parent(2)
b = a.something(3)
b.something_that_is_not_init()
3
Edited question a bit, updated code section since the question wasn't clear.
Yes, it's valid, but I don't recommend it. It's generally considered bad OOP programming. Also, you can create it as a static method so you never actually have to instantiate the parent class.
class parent():
def __init__(self, i):
self.i = i
#staticmethod
def foo(i):
c = child(i)
return c
class child(parent):
def bar(self):
print("Lucker number {}.".format(self.i)) # just to show the parent __init__ function is called
c = parent.foo(7)
c.bar() #=> Lucky number 7.
I just tried your example (including some missing self) and with python3 at least it works:
class Parent():
def __init__(self):
pass
def something(self):
a = child()
return a
class Child(parent):
def something_that_is_not_init(self):
print('yes, you got me')
and calling the something method works:
print(parent().something().__class__.__name__)
# Child
parent().something().something_that_is_not_init()
# yes, you got me
But maybe that's not very good design. Consider a factory or using __new__. But since you explicitly stated you wanted something like this: It works, even though I feel slightly spoiled writing it :-)
I want to be able to do the following
class Parent:
def __init__(self):
pass
def Create(self):
return 'Password'
class Child(Parent):
def __init__(self):
self.Create()
def Create(self):
return 'The '+self.Create #I want to return 'The Password'
I would like to get a parent function from a child class in a function that is overriding it. I am not sure how to do this.
This is a little hard to explain, comment if you are having trouble understanding.
Edit:
Thanks for the answers everyone, I almost thought that this was impossible.
The super() function is meant for cases like this. However, it only works on "new-style" classes, so you'll need to modify your definition of Parent to inherit from object as well (you should always be using "new-style" classes, anyway).
class Parent(object):
def __init__(self):
pass
def Create(self):
return 'Password'
class Child(Parent):
def __init__(self):
self.Create()
def Create(self):
return 'The ' + super(Child, self).Create()
print Child().Create() # prints "The Password"
Either refer to the parent explicitly or (in new-style classes) use super().
class Child(Parent):
...
def Create(self):
return 'The ' + Parent.Create(self)
Its as simple as referring to the base class via super:
class Child(Parent):
def __init__(self):
self.Create()
def Create(self):
return 'The '+ super(Child, self).Create()
Use the super function to access the parent super(Child,self).create() to call create from the parent.
You can use "super()" to call the super class method "Create()" as shown below:
class Parent:
def __init__(self):
pass
def Create(self):
return 'Password'
class Child(Parent):
def __init__(self):
self.Create()
def Create(self): # Here
return 'The ' + super().Create()
print(Child().Create()) # The Password