I wrote the following code. When I try to run it as at the end of the file I get this stacktrace:
AttributeError: 'super' object has no attribute do_something
class Parent:
def __init__(self):
pass
def do_something(self, some_parameter, next_parameter):
if type(some_parameter) is not int:
raise AttributeError("Some message")
if type(next_parameter) is not int:
raise AttributeError("Some message")
class Child(Parent):
def __init__(self):
super(Parent).__init__()
def do_something(self, some_parameter, next_parameter):
super(Parent).do_something(some_parameter, next_parameter)
return some_parameter + next_parameter
object = Child()
object.do_something(2, 2)
How should I solve this and where did I the mistake in this simply inheritance sample?
You're passing the wrong argument to super. If you're going to pass arguments at all, they need to be the current class and instance, not the parent class you're expecting to call. Or assuming you're using Python 3, you can skip the arguments completely and the compiler will make it work for you anyway. Calling super with one argument is allowed, but it returns an "unbound super object" which is almost never useful.
Change your calls to use one of these styles:
class Child(Parent):
def __init__(self):
super().__init__() # no arguments is almost always best in Python 3
def do_something(self, some_parameter, next_parameter):
super(Child, self).do_something(some_parameter, next_parameter) # name the current class
return some_parameter + next_parameter
I'd also note that your type checks in Parent.do_something are rather awkward. Rather than type(some_parameter) is not int, use isinstance(some_parameter, int) (unless you deliberately want to exclude subtypes).
You have a few issues here. Firstly there was an indentation error for the parent do_something definition. This meant that it was defined as a function in and of itself, rather than being a method of the class Parent.
Secondly, class methods should usually have self as their first parameter, as when they are called, the object that they refer to is passed as the first variable.
Thirdly, when you call super() you do not need to specify what the super is, as that is inherent in the class definition for Child.
Below is a fixed version of your code which should perform as you expect.
class Parent:
def __init__(self):
pass
def do_something(self, some_parameter, next_parameter):
if type(some_parameter) is not int:
raise AttributeError("Some message")
if type(next_parameter) is not int:
raise AttributeError("Some message")
class Child(Parent):
def __init__(self):
super(Parent).__init__()
def do_something(self, some_parameter, next_parameter):
super().do_something(some_parameter, next_parameter)
return some_parameter + next_parameter
test = Child()
test.do_something(2, 2)
Related
I am trying to do the following in python3:
class Parent:
#classmethod
def show(cls, message):
print(f'{message}')
#classmethod
def ask(cls, message):
cls.show(f'{message}???')
class Child(Parent):
#property
def name(self):
return 'John'
def show(self, message):
print(f'{self.name}: {message}')
instance = Child()
instance.ask('what')
But it then complains
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in ask
TypeError: Child.show() missing 1 required positional argument: 'message'
even so child.show works as expected. So it seems that child.ask is calling Parent.show... I tried to mark Child.show as classmethod too, but then the cls.name is not showing the expected output:
class Child2(Parent):
#property
def name(self):
return 'John'
#classmethod
def show(cls, message):
print(f'{cls.name}: {message}')
instance2 = Child2()
instance2.ask('what')
this shows
<property object at 0xfc7b90>: what???
Is there a way to override a parent classmethod with a non-classmethod, but keeping other parent classmethod to call the overridden one?
I found it hard to follow for the second half of the question but there was an issue I saw and it might help you solve your problem.
When you said even so child.show works as expected. So it seems that child.ask is calling Parent.show, thats not what is happening.
When you called instance.ask("what"), it called the #classmethod decorated method of the Child class (which is inherited from the parent). This ask method is passing the class Child as the first argument, (not the instance you created). This means the line
cls.show(f'{message}???')
is equivalent to
Child.show(f'{message}???') # because cls is the Class not the instance
The show method inside the Child class is an instance method and expects the first argument to be the actual instance (self) but the string f'{message}???' is being passed to it and it expects a second message string to be passed so that's why its is throwing an error.
Hope this helped
hey guys need to know as of how to start a method in a classA from class B
have
classA(object):
def __init__(self):
#this is where the ClassB method'' def multiplyPeople() ''should be called or started.
classB(object):
def multiplyPeople(self):
its giving an error
TypeError: unbound method multiplyPeople() must be called
with classB instance as first argument (got nothing instead)
know this is something basic, but am trying to figure out what exactly is supposed to be done and where am I getting lost.
I have called it as
classA(object):
def__init__(self):
self.PeopleVariable=classB.multiplyPeople()
It depends on how you want the function to work. Do you just want to use the class as a placeholder? Then you can use a so called static method for which you do not need to instantiate an object.
Or you can use a regular method and use it on a created object (notice that there you have access to self)
class A():
def __init__(self):
b = B()
b.non_static()
B.multiplyPeople()
class B():
#staticmethod
def multiplyPeople():
print "this was called"
def non_static(self):
print self, " was called"
if __name__ == "__main__":
a = A()
output:
<__main__.B instance at 0x7f3d2ab5d710> was called
this was called
I was just pulling off a toy example for myself, but it is not working and I cannot make it work. Does anybody know why this is not working and how to make it work:
class A(object):
#def __init__():
#pass
def do1():
print("foo")
def do2():
print("Hello")
Al = A
Al.do1()
TypeError: unbound method do1() must be called with A instance as first argument (got nothing instead)
In your code variable A1 it's reference to your class not instance, create instance of your class
Al = A()
and run your method
Al.do1()
You need to call your class to crate a correct instance and pass the self keyword to enclosing function to provides a handle back to the instance to be processed :
class A(object):
#def __init__():
#pass
def do1(self):
print("foo")
def do2():
print("Hello")
Al = A()
Al.do1()
Note that without passing the self to your function after calling it you will get a TypeError.
TypeError: do1() takes 0 positional arguments but 1 was given
Or as #Padraic Cunningham mentioned in comment you can use staticmethod as a decorator to wrap your function which makes python doesn't pass the first default argument (self) to it.
class A(object):
#def __init__():
#pass
#staticmethod
def do1():
print("foo")
def do2():
print("Hello")
Al = A()
Al.do1()
Here is my program structure:
class parent(object):
def __init__(self): pass
def __post_init_stuff(self):
#post initialization stuff
class child(parent):
def __init__(self):
#dostuff
self.__post_init_stuff()
def otherfunc(classname, args):
classname(args)
otherfunc(child)
The problem that I'm having is that when otherstuff(child) executes, I get this error:
AttributeError: 'child' object has no attribute '_child__post_init_stuff'
Any advice?
Names that start with __ in Python are like protected in C++. You could name with only one underscore instead or access it as self._parent__post_init_func, since this is its mangled name within the scope. I recommend the first thing, since this is ugly and hacky.
In Smalltalk there is a message DoesNotUnderstand that is called when an object does not understand a message (this is, when the object does not have the message sent implemented).
So, I like to know if in python there is a function that does the same thing.
In this example:
class MyObject:
def __init__(self):
print "MyObject created"
anObject = MyObject() # prints: MyObject created
anObject.DoSomething() # raise an Exception
So, can I add a method to MyObject so I can know when DoSomething is intented to be called?
PS: Sorry for my poor English.
Here is a proposition for what you want to do:
class callee:
def __init__(self, name):
self.name = name
def __call__(self):
print self.name, "has been called"
class A:
def __getattr__(self, attr):
return callee(attr)
a = A()
a.DoSomething()
>>> DoSomething has been called
You are looking for the __getattr__ method. Have a look here.
If you want "total control" of a class, look at the __getattribute__ special method then (here).
Have you looked at object.__getattr__(self, name), or object.__getattribute__(self, name) for new-style classes? (see Special method names, Python language reference)
I don't know why luc had the two separate classes. You can do it all with one class, if you use a closure. Like so:
class A(object):
__ignored_attributes__ = set(["__str__"])
def __getattr__(self, name):
if __name__ in self.__ignored_attributes__:
return None
def fn():
print name, "has been called with self =", self
return fn
a = A()
a.DoSomething()
I added the bit about __ignored_attributes__ because Python was looking up __str__ in the class and that got a little messy.