Python error while working with class - Unbound method - python

I am trying to create a class with multiple functions, accepts a string as an argument and prints this string. So far this is what I have written:
class test():
def func(self,text):
print str(text)
test.func('This is a bunch of text')
To which I get the following error message:
_Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method func() must be called with test instance as first argument (got str instance instead)_
Any suggestions?

You need to instantiate a class before you can call an instance method:
class Test(object):
def func(self, text):
print str(text)
test = Test()
test.func('This is a bunch of text')

Or you can try -
class test():
#staticmethod
def func(text):
print str(text)
test.func('This is a bunch of text')

Related

How to define a custom function of an instance using setattr

I'm trying to add a method to a class dynamically, but I keep running into an error where self is not passed to a the new function. For instance:
class Dummy():
def say_hi(self):
print("hi")
def new_method(self):
print("bye")
dummy = Dummy()
setattr(dummy, "say_bye", new_method)
dummy.say_bye()
results in the following error:
Traceback (most recent call last):
File "main.py", line 13, in <module>
dummy.say_bye()
TypeError: new_method() missing 1 required positional argument: 'self'
What am I doing wrong?
Use types.MethodType feature:
from types import MethodType
class Dummy():
def say_hi(self):
print("hi")
def new_method(self):
print("bye")
dummy = Dummy()
dummy.say_bye = MethodType(new_method, dummy)
dummy.say_bye() # bye
You are setting the function new_method as an attribute of the dummy object.
If you do print(dummy.__dict__) you'll see something like this:
{'say_bye': <function new_method at 0x7fcd949af668>}
This means that your dummy object has the function new_method as an attribute, so when you do dummy.say_bye(), you're calling the function you have as an attribute without any argument.
It is not a function of the Dummy class, it is just a function that your dummy object has as an attribute.
You can achieve the functionality you are looking for using RomanPerekhrest's answer.
Hope it helps.
Cheers!

Why do we provide the object as an argument to super()?

In the python docs, one can read the following about super():
If the second argument is omitted, the super object returned is
unbound.
They are referring to the second argument in super(class_name, second_argument). What does it mean for an object to be unbound? I've heard of unbound methods, meaning they don't exist on any object, but on a class (please correct me if I'm wrong), but what is an unbound object?
Here is a code example provided in the same docs. It shows a typical call to super() in order to get the overridden method of the superclass.
class C(B):
def method(self, arg):
super(C, self).method(arg)
As you can see, they do use the second argument here. Why should we do that? What would happen if we didn't?
EDIT: I tried the following...
class B(object):
def method(self, arg):
print(arg)
class C(B):
def method(self, arg):
super(C, self).method(arg)
class D(B):
def method(self, arg):
super(D).method(arg)
c = C()
d = D()
c.method("hi")
d.method("hi again")
The call to c.method() worked fine, printing "hi", but the second call, to d.method(), crashed:
n132-p95:Desktop sahandzarrinkoub$ python2 super.py
hi
Traceback (most recent call last):
File "super.py", line 17, in <module>
d.method("hi again")
File "super.py", line 11, in method
super(D).method(arg)
AttributeError: 'super' object has no attribute 'method'

Using a method from the parent class

I want to call a method from the parent class in a child class.
I use XX.__init__() in my child class and call the press function from the parent class. But it fails when I run the following code:
Func.py
class PC:
def __init__(self):
PCKeyDis = {}
self.PCKeyDis = PCKeyDis
def Press(self,key):
KeyDis = self.PCKeyDis
if len(key)==1 and key.islower():
key = key.upper()
win32api.keybd_event(KeyDis[key],0,0,0)
time.sleep(0.1)
win32api.keybd_event(KeyDis[key],0,win32con.KEYEVENTF_KEYUP,0)
class PCFunc(PC):
def __init__(self):
pass
def Sentence(self,string):
PC.__init__()
strlist = list(string)
for i in xrange(len(strlist)):
if strlist[i] == ' ':
strlist[i] = 'Space'
PC.Press(strlist[i]) #use this function
action.py
import Func
import win32gui
PC = Func.PC()
PCFunc = Func.PCFunc ()
win32gui.SetForegroundWindow(win32gui.FindWindow(winclass,winnm))
PCFunc.Sentence(path)
I get:
unbound method Sentence() must be called with PCFunc instance as first argument (got str instance instead)
If you want to call the constructor of the base class, then you do it on instantiation in the __init__() method, not in the Sentence() method:
def __init__(self):
super(self.__class__, self).__init__()
Since Sentence() is an instance method, you need to call it via an instance of the class (like the error tells you):
pc_func = PCFunc()
pc_func.Sentence(var)
Here you are calling the method with an undefined variable:
PCFunc.Sentence(path)
Instead you need to give a string as parameter, so either write Sentence('path'), or define the variable first:
path = 'my path'
pc_func.Sentence(path)
Do not use the same name as the class name for an instance of the class:
PCFunc = Func.PCFunc ()
Otherwise the variable name storing the instance overwrites the class name.
Apart from that, it is unclear what your code is actually supposed to do. Have a look at the Python code conventions for a first step to making your code more readible. Then do some research about classes and inheritance.
The code you posted does not produce the error you posted. Here is an example that will produce that error:
class Dog:
def do_stuff(self, string):
print string
d = Dog()
d.do_stuff('hello')
Dog.do_stuff(d, 'goodbye')
Dog.do_stuff('goodbye')
--output:--
hello
goodbye
Traceback (most recent call last):
File "1.py", line 9, in <module>
Dog.do_stuff('goodbye')
TypeError: unbound method do_stuff() must be called with Dog instance as first argument (got str instance instead)
An __init__() function can also produce that error:
class Dog:
def __init__(self):
pass
def do_stuff(self, string):
print(string)
Dog.__init__()
--output:--
Traceback (most recent call last):
File "1.py", line 7, in <module>
Dog.__init__()
TypeError: unbound method __init__() must be called with Dog instance as first argument (got nothing instead)
In the line:
d.do_stuff('hello')
the fragment d.do_stuff causes python to create and return a bound method object--which is then immediately executed by the function execution operator () in the fragment ('hello’). The bound method is bound to the instance d, hence the reason it is called a bound method. A bound method automatically passes the instance it contains to the method when the method is executed.
On the other hand, when you write:
Dog.do_stuff(....)
the fragment Dog.do_stuff causes python to create and return an unbound method. An unbound method does not contain an instance, so when an unbound method is executed by the function execution operator (), you must manually pass an instance. (In python3, things changed and you can pass anything as the first argument--an instance of the class isn't required.)

Extending a class in nltk. - python

The aim is to add additional functions to the wordnet class in nltk, e.g.:
from nltk.corpus import wordnet
class WN(wordnet):
def foobar(self):
print 'foobar'
x = WN
WN.foobar()
but it gives an error:
Traceback (most recent call last):
File "/home/alvas/workspace/pybabel-fresh/babelnet/utils/pybabel_WordNet.py", line 5, in <module>
class WN(wordnet):
File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/util.py", line 44, in __init__
assert issubclass(reader_cls, CorpusReader)
TypeError: Error when calling the metaclass bases
issubclass() arg 1 must be a class
So I tried with nltk.corpus.reader.WordNetCorpusReader
(http://www.nltk.org/_modules/nltk/corpus/reader/wordnet.html#WordNetCorpusReader):
from nltk.corpus.reader import WordNetCorpusReader
class WN(WordNetCorpusReader):
def __init__(self):
self = WN.__init__()
def foobar(self):
return "foobar"
x = WN
x.foobar()
Still it seems like if I'm using WordNetCorpusReader, I need to instantiate it, so I got:
Traceback (most recent call last):
File "/home/alvas/workspace/pybabel-fresh/babelnet/utils/pybabel_WordNet.py", line 13, in <module>
x.foobar()
TypeError: unbound method foobar() must be called with WN instance as first argument (got nothing instead)
Then I tried:
from nltk.corpus.reader import WordNetCorpusReader
class WN(WordNetCorpusReader):
def foobar(self):
return "foobar"
x = WN
for i in x.all_synsets():
print i
[out]:
Traceback (most recent call last):
File "/home/alvas/workspace/pybabel-fresh/babelnet/utils/pybabel_WordNet.py", line 10, in <module>
for i in x.all_synsets():
TypeError: unbound method all_synsets() must be called with WN instance as first argument (got nothing instead)
How do I extend the nltk wordnet API with new functions? Note: that the aim is to create a new class with the new functions.
Your second attempt seems closest. The problem there is with your constructor:
class WN(WordNetCorpusReader):
def __init__(self):
self = WN.__init__() # needs an instance as the first argument, recursive, and no need to assign to self
The __init__ method needs an instance as its first argument (here self), and in addition you are calling the __init__ method of the wrong class. This will lead to a RuntimeError: maximum recursion depth exceeded error. Finally, you simply want to call the method; you don't need to assign the results of the method to self.
I think you meant to do this instead:
from nltk.corpus.reader import WordNetCorpusReader
import nltk
class WN(WordNetCorpusReader):
def __init__(self, *args):
WordNetCorpusReader.__init__(self, *args)
def foobar(self):
return "foobar"
The catch is, though, that you will need to pass the required WordNetCorpusReader.__init__ args to your new class. In my version of nltk, that means you will need to pass a root argument as follows:
>>> x = WN(nltk.data.find('corpora/wordnet'))
>>> x.foobar()
'foobar'
>>> x.synsets('run')
[Synset('run.n.01'), Synset('test.n.05'), ...]
A more efficient approach
A much more efficient way to do the same thing is as follows:
class WN(WordNetCorpusReader):
root = nltk.data.find('corpora/wordnet') # make root a class variable, so you only need to load it once
def __init__(self, *args, **kwargs):
WordNetCorpusReader.__init__(self, WN.root, *args, **kwargs) # add root yourself here, so no arguments are required
def foobar(self):
return "foobar"
Now test it:
>>> x = WN()
>>> x.foobar()
'foobar'
>>> x.synsets('run')
[Synset('run.n.01'), Synset('test.n.05'), ...]
By the way, I've enjoyed seeing your work on the nltk tag.

Python class can't see method unless I comment out __init__

The following code only works if I comment out the initialiser.
class What:
def __init__(self):
pass
def method1(self):
print 'method1'
def main():
b = What()
if hasattr(b,"method1"):
print "b.method1"
b.method1()
main()
If it's not commented out I get the error message…
Traceback (most recent call last):
File "strange.py", line 17, in <module>
main()
File "strange.py", line 15, in main
b.method1()
AttributeError: What instance has no attribute 'method1'
However if I type in an identical method and call it, there is no problem at all…
def method2(self):
print 'method2'
I've od -c the file and there are no strange characters in the text
Using Python 2.7.2
I think you are mixing tabs and spaces.
With the code using 4 spaces per indent (spaces in accordance with pep8) it works fine. But this
class What:
def __init__(self):
pass
def method1(self):
print 'method1'
def main():
b = What()
if hasattr(b,"method1"):
print "b.method1"
b.method1()
main()
Is what Python would see if you had tabs for method1, and this will generate the error you see.

Categories

Resources