What does "bound method" error mean when I call a function? - python

I am creating a word parsing class and I keep getting a
bound method Word_Parser.sort_word_list of <__main__.Word_Parser instance at 0x1037dd3b0>
error when I run this:
class Word_Parser:
"""docstring for Word_Parser"""
def __init__(self, sentences):
self.sentences = sentences
def parser(self):
self.word_list = self.sentences.split()
def sort_word_list(self):
self.sorted_word_list = self.word_list.sort()
def num_words(self):
self.num_words = len(self.word_list)
test = Word_Parser("mary had a little lamb")
test.parser()
test.sort_word_list()
test.num_words()
print test.word_list
print test.sort_word_list
print test.num_words

There's no error here. You're printing a function, and that's what functions look like.
To actually call the function, you have to put parens after that. You're already doing that above. If you want to print the result of calling the function, just have the function return the value, and put the print there. For example:
print test.sort_word_list()
On the other hand, if you want the function to mutate the object's state, and then print the state some other way, that's fine too.
Now, your code seems to work in some places, but not others; let's look at why:
parser sets a variable called word_list, and you later print test.word_list, so that works.
sort_word_list sets a variable called sorted_word_list, and you later print test.sort_word_list—that is, the function, not the variable. So, you see the bound method. (Also, as Jon Clements points out, even if you fix this, you're going to print None, because that's what sort returns.)
num_words sets a variable called num_words, and you again print the function—but in this case, the variable has the same name as the function, meaning that you're actually replacing the function with its output, so it works. This is probably not what you want to do, however.
(There are cases where, at first glance, that seems like it might be a good idea—you only want to compute something once, and then access it over and over again without constantly recomputing that. But this isn't the way to do it. Either use a #property, or use a memoization decorator.)

This problem happens as a result of calling a method without brackets. Take a look at the example below:
class SomeClass(object):
def __init__(self):
print 'I am starting'
def some_meth(self):
print 'I am a method()'
x = SomeClass()
''' Not adding the bracket after the method call would result in method bound error '''
print x.some_meth
''' However this is how it should be called and it does solve it '''
x.some_meth()

You have an instance method called num_words, but you also have a variable called num_words. They have the same name. When you run num_words(), the function replaces itself with its own output, which probably isn't what you want to do. Consider returning your values.
To fix your problem, change def num_words to something like def get_num_words and your code should work fine. Also, change print test.sort_word_list to print test.sorted_word_list.

For this thing you can use #property as an decorator, so you could use instance methods as attributes. For example:
class Word_Parser:
def __init__(self, sentences):
self.sentences = sentences
#property
def parser(self):
self.word_list = self.sentences.split()
#property
def sort_word_list(self):
self.sorted_word_list = self.word_list.sort()
#property
def num_words(self):
self.num_words = len(self.word_list)
test = Word_Parser("mary had a little lamb")
test.parser()
test.sort_word_list()
test.num_words()
print test.word_list
print test.sort_word_list
print test.num_words
so you can use access the attributes without calling (i.e., without the ()).

I think you meant print test.sorted_word_list instead of print test.sort_word_list.
In addition list.sort() sorts a list in place and returns None, so you probably want to change sort_word_list() to do the following:
self.sorted_word_list = sorted(self.word_list)
You should also consider either renaming your num_words() function, or changing the attribute that the function assigns to, because currently you overwrite the function with an integer on the first call.

The syntax problem is shadowing method and variable names. In the current version sort_word_list() is a method, and sorted_word_list is a variable, whereas num_words is both. Also, list.sort() modifies the list and replaces it with a sorted version; the sorted(list) function actually returns a new list.
But I suspect this indicates a design problem. What's the point of calls like
test.parser()
test.sort_word_list()
test.num_words()
which don't do anything? You should probably just have the methods figure out whether the appropriate counting and/or sorting has been done, and, if appropriate, do the count or sort and otherwise just return something.
E.G.,
def sort_word_list(self):
if self.sorted_word_list is not None:
self.sorted_word_list = sorted(self.word_list)
return self.sorted_word_list
(Alternately, you could use properties.)

Your helpful comments led me to the following solution:
class Word_Parser:
"""docstring for Word_Parser"""
def __init__(self, sentences):
self.sentences = sentences
def parser(self):
self.word_list = self.sentences.split()
word_list = []
word_list = self.word_list
return word_list
def sort_word_list(self):
self.sorted_word_list = sorted(self.sentences.split())
sorted_word_list = self.sorted_word_list
return sorted_word_list
def get_num_words(self):
self.num_words = len(self.word_list)
num_words = self.num_words
return num_words
test = Word_Parser("mary had a little lamb")
test.parser()
test.sort_word_list()
test.get_num_words()
print test.word_list
print test.sorted_word_list
print test.num_words
and returns:
['mary', 'had', 'a', 'little', 'lamb']
['a', 'had', 'lamb', 'little', 'mary']
5
Thank you all.

Bound method error also occurs (in a Django app for instnce) , if you do a thing as below:
class Products(models.Model):
product_category = models.ForeignKey(ProductCategory, on_delete=models.Protect)
def product_category(self)
return self.product_category
If you name a method, same way you named a field.

Related

infinite recursion when printing instance in python

I get a Runtime error (maximum recursion) when I execute the following code.
I'm trying to generate a list of instances; then I would like to print each one. I'm not sure what's going on here.
Anyway, what is the correct way to access each instance from the instance list?
I do realize I'm using a string of digits to name the instances and this is not cool. But say each number on the list is associated with a bunch of information. Then having attributes for each could make things accessible. I tried using a dict but I end up with nested dicts and I just didn't like it.
Thanks in advance.
class MyClass(object):
def __str__(self):
stuff= str(self)
return stuff
mylist = ['1234567','8910111','1213144','7654321']
inslist = [MyClass() for i in mylist]
print inslist[0]
The problem is in your __str__. If you call str(self), it will call itself. I think you meant was this:
class MyClass(object):
def __init__(self, i):
self.i = i
def __str__(self):
return str(self.i)
mylist = ['1234567','8910111','1213144','7654321']
inslist = [MyClass(i) for i in mylist]
print inslist[0]

Python function, overwrite original variable

I have this function:
def icaocode(code):
c.execute("SELECT ICAO, LAT, LON FROM airports WHERE ICAO = ?", (code,))
result = c.fetchone()
if result is None:
print("No airport found with ICAO code", code)
sys.exit()
else:
print("Found", code)
[...]
Lets say I call this function with
icaocode(x)
How do I get the function to overwrite x with the results?
In function def:
def icaocode(code):
...
return code # new value
When calling:
x = icaocode(x)
Btw if the argument is mutable (like a list), you can overwrite it without returning the new value. If it's immutable (like a string, integer), you can't.
E.g.
def f(some_list):
some_list.append("something")
In this case
my_list = []
f(my_list)
my_list will be ["something"]
You can't overwrite the value of the parameter. That is, you can't change it to refer to another object. You can, however, change the object. There is an old thread on pass-by-value and pass-by-reference semantics in Python that you may find illuminating: https://stackoverflow.com/a/986145/399047
For example, you can append elements to a list that is passed in as a parameter. The following code:
def func(a_list):
a_list.append("some value")
l = [1,2,3]
print l
func(l)
print l
would give:
[1,2,3]
[1,2,3,"some value"]
In contrast, a string, cannot be modified. The following code:
def func2(a_str):
a_str += "suffix"
s = "test"
print s
func2(s)
print s
would give:
"test"
"test"
My recommendation, unless you have a good reason, is to avoid mutating your input parameters, and return the modified object instead. Side-effects can make for messy code.
If, at the end of all this you really want to modify your input parameter, one technique would be to wrap the code parameter inside another object. e.g.
def icaocode(code_list):
input_code = code_list[0]
[...]
# do something to input_code, assign result to
# output_code
[...]
code_list[0] = output_code
Then you would call with:
code_list = [code]
icaocode(code_list)
That said, this code is ugly to me, smells something awful, and I don't recommend it.
You can, but it is a horrible way to conduct business. Return the value instead, remember that you can return more than one value if you like. Here is however one way to return a value through a parameter. But don't use it.
>>> def a(b):
... b[0] = 'hi'
....
>>> c = ['nono']
>>> a(c)
>>> print(c)
['hi']

Unit test for the 'none' type in Python

How would I go about testing for a function that does not return anything?
For example, say I have this function:
def is_in(char):
my_list = []
my_list.append(char)
and then if I were to test it:
class TestIsIn(unittest.TestCase):
def test_one(self):
''' Test if one character was added to the list'''
self.assertEqual(self.is_in('a'), # And this is where I am lost)
I don't know what to assert the function is equal to, since there isn't any return value that I could compare it to.
Would assertIn work?
All Python functions return something. If you don't specify a return value, None is returned. So if your goal really is to make sure that something doesn't return a value, you can just say
self.assertIsNone(self.is_in('a'))
(However, this can't distinguish between a function without an explicit return value and one which does return None.)
The point of a unit test is to test something that the function does. If it's not returning a value, then what is it actually doing? In this case, it doesn't appear to be doing anything, since my_list is a local variable, but if your function actually looked something like this:
def is_in(char, my_list):
my_list.append(char)
Then you would want to test if char is actually appended to the list. Your test would be:
def test_one(self):
my_list = []
is_in('a', my_list)
self.assertEqual(my_list, ['a'])
Since the function does not return a value, there isn't any point testing for it (unless you need make sure that it doesn't return a value).

How to implement a submethod in a Python-class?

I appologize, if I didn't express my self clearly. What I want to do is this:
class someClass(object):
def aMethod(self, argument):
return some_data #for example a list or a more complex datastructure
def aMethod_max(self, argument):
var = self.aMethod(argument)
#do someting with var
return altered_var
or I could do:
def aMethod(self, argument):
self.someVar = some_data
return some_data #for example a list or a more complex datastructure
def aMethod_max(self, argument):
if not hasattr(self, someVar):
self.aMethod(argument)
#do someting with self.var
return altered_var
But I considered this too complicated and hoped for a more elegant solution. I hope that it's clear now, what I want to accomplish.
Therefore I phantasized about something like in the following paragraph.
class someClass(object):
someMethod(self):
#doSomething
return result
subMethod(self):
#doSomething with the result of someMethod
Foo = someClass()
Foo.someMethod.subMethod()
or if someMethod has an argument something like
Foo.someMethod(argument).subMethod()
How would I do something like this in python?
EDIT: or like this?
subMethod(self):
var = self.someMethod()
return doSomething(var)
Let's compare the existing solutions already given in your question (e.g. the ones you call "complicated" and "inelegant") with your proposed alternative.
The existing solutions mean you will be able to write:
foo.subMethod() # foo.someMethod() is called internally
but your proposed alternative means you have to write:
foo.someMethod().subMethod()
which is obviously worse.
On the other hand, if subMethod has to be able to modify the result of any method, rather than just someMethod, then the existing solutions would mean you have to write:
foo.subMethod(foo.anyMethod())
with the only disadvantage here being that you have to type foo twice, as opposed to once.
Conclusion: on the whole, the existing solutions are less complicated and inelegant than your proposed alternative - so stick with the existing solutions.
You can do method chaining when the result of someMethod is an instance of someClass.
Simple example:
>>> class someClass:
... def someMethod(self):
... return self
... def subMethod(self):
... return self.__class__
...
>>> x=someClass()
>>> x
<__main__.someClass instance at 0x2aaaaab30d40>
>>> x.someMethod().subMethod()
<class __main__.someClass at 0x2aaaaab31050>
Not sure if I'm understanding it right, but perhaps you mean this:
Foo.subMethod(Foo.someMethod())
This passes the result of someMethod() to subMethod(). You'd have to change your current definition of subMethod() to accept the result of someMethod().
You can achieve something similar using decorators:
def on_result(f):
def decorated(self,other,*args,**kwargs):
result = getattr(self,other)(*args,**kwargs)
return f(result)
return decorated
Usage:
class someClass(object):
def someMethod(self,x,y):
#doSomething
result = [1,2,3,x,y] # example
return result
#on_result
def subMethod(self):
#doSomething with the result of someMethod
print self # example
Foo = someClass()
Foo.subMethod("someMethod",4,5)
Output:
[1, 2, 3, 4, 5]
As you see, the first argument is the name of the method to be chained, and the remaining ones will be passed to it, no matter what its signature is.
EDIT: on second thought, this is rather pointless, since you could always use
Foo.submethod(Foo.someMethod(4,5))...
Maybe I didn't understand what you're trying to achieve. Does the subMethod have to be linked to a specific method only? Or maybe it's the syntatic form
a.b().c()
that's important to you? (in that case, see kojiro's answer)
From the feedback so far, I understand that subMethod will link only to someMethod, right? Maybe you can achieve this combining a decorator with a closure:
def on_result(other):
def decorator(f):
def decorated(self,*a1,**k1):
def closure(*a2,**k2):
return f(self,getattr(self,other)(*a1,**k1),*a2,**k2)
return closure
return decorated
return decorator
class someClass(object):
def someMethod(self,a,b):
return [a,2*b]
#on_result('someMethod')
def subMethod(self,result,c,d):
result.extend([3*c,4*d])
return result
Foo = someClass()
print Foo.subMethod(1,2)(3,4) # prints [1,4,9,16]
The decorator is kinda "ugly", but once written it's usage is quite elegant IMHO (plus, there are no contraints in the signature of either method).
Note: I'm using Python 2.5 and this is the only way I know of writing decorators that take arguments. There's probably a better way, but I'm too lazy to look it up right now...

How to call Python functions dynamically [duplicate]

This question already has answers here:
Calling a function of a module by using its name (a string)
(18 answers)
Closed 4 months ago.
I have this code:
fields = ['name','email']
def clean_name():
pass
def clean_email():
pass
How can I call clean_name() and clean_email() dynamically?
For example:
for field in fields:
clean_{field}()
I used the curly brackets because it's how I used to do it in PHP but obviously doesn't work.
How to do this with Python?
If don't want to use globals, vars and don't want make a separate module and/or class to encapsulate functions you want to call dynamically, you can call them as the attributes of the current module:
import sys
...
getattr(sys.modules[__name__], "clean_%s" % fieldname)()
Using global is a very, very, bad way of doing this. You should be doing it this way:
fields = {'name':clean_name,'email':clean_email}
for key in fields:
fields[key]()
Map your functions to values in a dictionary.
Also using vars()[] is wrong too.
It would be better to have a dictionary of such functions than to look in globals().
The usual approach is to write a class with such functions:
class Cleaner(object):
def clean_name(self):
pass
and then use getattr to get access to them:
cleaner = Cleaner()
for f in fields:
getattr(cleaner, 'clean_%s' % f)()
You could even move further and do something like this:
class Cleaner(object):
def __init__(self, fields):
self.fields = fields
def clean(self):
for f in self.fields:
getattr(self, 'clean_%s' % f)()
Then inherit it and declare your clean_<name> methods on an inherited class:
cleaner = Cleaner(['one', 'two'])
cleaner.clean()
Actually this can be extended even further to make it more clean. The first step probably will be adding a check with hasattr() if such method exists in your class.
I have come across this problem twice now, and finally came up with a safe and not ugly solution (in my humble opinion).
RECAP of previous answers:
globals is the hacky, fast & easy method, but you have to be super consistent with your function names, and it can break at runtime if variables get overwritten. Also it's un-pythonic, unsafe, unethical, yadda yadda...
Dictionaries (i.e. string-to-function maps) are safer and easy to use... but it annoys me to no end, that i have to spread dictionary assignments across my file, that are easy to lose track of.
Decorators made the dictionary solution come together for me. Decorators are a pretty way to attach side-effects & transformations to a function definition.
Example time
fields = ['name', 'email', 'address']
# set up our function dictionary
cleaners = {}
# this is a parametered decorator
def add_cleaner(key):
# this is the actual decorator
def _add_cleaner(func):
cleaners[key] = func
return func
return _add_cleaner
Whenever you define a cleaner function, add this to the declaration:
#add_cleaner('email')
def email_cleaner(email):
#do stuff here
return result
The functions are added to the dictionary as soon as their definition is parsed and can be called like this:
cleaned_email = cleaners['email'](some_email)
Alternative proposed by PeterSchorn:
def add_cleaner(func):
cleaners[func.__name__] = func
return func
#add_cleaner
def email():
#clean email
This uses the function name of the cleaner method as its dictionary key.
It is more concise, though I think the method names become a little awkward.
Pick your favorite.
globals() will give you a dict of the global namespace. From this you can get the function you want:
f = globals()["clean_%s" % field]
Then call it:
f()
Here's another way:
myscript.py:
def f1():
print 'f1'
def f2():
print 'f2'
def f3():
print 'f3'
test.py:
import myscript
for i in range(1, 4):
getattr(myscript, 'f%d' % i)()
I had a requirement to call different methods of a class in a method of itself on the basis of list of method names passed as input (for running periodic tasks in FastAPI). For executing methods of Python classes, I have expanded the answer provided by #khachik. Here is how you can achieve it from inside or outside of the class:
>>> class Math:
... def add(self, x, y):
... return x+y
... def test_add(self):
... print(getattr(self, "add")(2,3))
...
>>> m = Math()
>>> m.test_add()
5
>>> getattr(m, "add")(2,3)
5
Closely see how you can do it from within the class using self like this:
getattr(self, "add")(2,3)
And from outside the class using an object of the class like this:
m = Math()
getattr(m, "add")(2,3)
Here's another way: define the functions then define a dict with the names as keys:
>>> z=[clean_email, clean_name]
>>> z={"email": clean_email, "name":clean_name}
>>> z['email']()
>>> z['name']()
then you loop over the names as keys.
or how about this one? Construct a string and use 'eval':
>>> field = "email"
>>> f="clean_"+field+"()"
>>> eval(f)
then just loop and construct the strings for eval.
Note that any method that requires constructing a string for evaluation is regarded as kludgy.
for field in fields:
vars()['clean_' + field]()
In case if you have a lot of functions and a different number of parameters.
class Cleaner:
#classmethod
def clean(cls, type, *args, **kwargs):
getattr(cls, f"_clean_{type}")(*args, **kwargs)
#classmethod
def _clean_email(cls, *args, **kwargs):
print("invoked _clean_email function")
#classmethod
def _clean_name(cls, *args, **kwargs):
print("invoked _clean_name function")
for type in ["email", "name"]:
Cleaner.clean(type)
Output:
invoked _clean_email function
invoked _clean_name function
I would use a dictionary which mapped field names to cleaning functions. If some fields don't have corresponding cleaning function, the for loop handling them can be kept simple by providing some sort of default function for those cases. Here's what I mean:
fields = ['name', 'email', 'subject']
def clean_name():
pass
def clean_email():
pass
# (one-time) field to cleaning-function map construction
def get_clean_func(field):
try:
return eval('clean_'+field)
except NameError:
return lambda: None # do nothing
clean = dict((field, get_clean_func(field)) for field in fields)
# sample usage
for field in fields:
clean[field]()
The code above constructs the function dictionary dynamically by determining if a corresponding function named clean_<field> exists for each one named in the fields list. You likely would only have to execute it once since it would remain the same as long as the field list or available cleaning functions aren't changed.

Categories