Python How to call a method from inside another method - python

I am a new OOP. I have written the following classes and methods and want to call a method from inside another method. However, I get an error saying name polynomial (method) is not defined. Any ideas why?
#Imports
import numpy as np
from scipy.signal import argrelextrema
from scipy import optimize
class MaxImpact():
def __init__(self,X,Y):
self.X = X
self.Y = Y
self.minima_index = argrelextrema(self.Y,np.less)
self.maxima_index = argrelextrema(self.Y,np.greater)
self.approx_converge_pt = []
self.approx_converge_idx = []
# .... (bunch of other methods)
def calc_convergePt_X(self):
for i in range(1,len(self.Y)):
if (self.Y[i-1] < 0 and self.Y[i] > 0) or (self.Y[i-1] > 0 and self.Y[i] < 0):
self.approx_converge_idx.append(i-1)
for i in self.approx_converge_idx:
self.x_val = self.X[i]
return(self.x_val)
def polynomial(self):
func = clf4.intercept_[0] + clf4.coef_[0][1] * self.X + clf4.coef_[0][2]*np.power(self.X,2) + clf4.coef_[0][3]*np.power(self.X,3) + clf4.coef_[0][4]*np.power(self.X,4)
def neutral_state(self):
sol = optimize.root(polynomial(),self.x_val)
maxImp2 = MaxImpact(XX,YY4)
print(maxImp2.calc_convergePt_X())
print(maxImp2.neutral_state())
Here I want to call the polynomial method which contains the polynomial eq within the neutral state method. I end up with the error "name polynomial is not defined"

Methods must be called on an instance. To call a method on the same instance, use self to refer to it:
def neutral_state(self):
sol = optimize.root(self.polynomial(), self.x_val)

please use self keyword while calling the class member.
sol = optimize.root(self.polynomial(),self.x_val)

Python is raising a NameError because as far as it's concerned, polynomial doesn't exist. You've defined it as a method of the MaxImpact class, and therefore the function will only be called when you call self.polynomial(), telling python that it is part of the MaxImpact class.

To call a method when using OOP in Python, and in this case, you can simply use self.methodname()
In your case:
class return_hello():
def polynomial(self):
return print("hello")
def neutral_state(self):
self.polynomial()

Related

How do I get python to read that () is 0?

I'm having issues trying to pass an empty parameter can someone explain to me why my code isn't working. I have a math test file that goes through my math library file but my lib file can't read the () code. When I run the code it says init() missing 1 required positional argument: 'y'
import MathLib as math
math test:
if __name__ == '__main__':
math_obj1 = math.MyMathLib(2.0)
math_obj2 = math.MyMathLib(-0.5)
math_obj3 = math.MyMathLib() # this should give 0.0
print("Math obj1 value = ",math_obj1.get_curr_value() )
print("Math obj2 value = ",math_obj2.get_curr_value() )
print("Math obj3 value = ",math_obj3.get_curr_value() )
import math
class MyMathLib:
def __init__(self, y,):
self.y = y
if self == None:
value == 0.0
As posted, your definition of the __init__() function has y as a required argument.
If you want it to be optional and have a default value of zero, then write it this way:
class MyMathLib:
def __init__(self, y=0.0):
The self variable isn't actually a passable parameter in class methods (I recommend you take another look at python classes). The first (and only) passable parameter in your init function is y. Since y has no default variable, you must pass a value for y, or give it a default value:
def __init__(self, y=0.0):
self.y = y
Also I'm not sure what you're trying to achieve with this line, it makes no sense:
if self == None:
value == 0.0
value is only local to the init function, maybe you meant self.value? Even then, self will never be None (unless you assign self = None within the method), so the statement will never trigger. Ontop of that, you've used a double == instead of =.
You have to set default value in __init__
def __init__(self, y=0.0):
self.y = y
and then you don't have to check None
Or using None
def __init__(self, y=None):
self.y = y
if self.y is None:
self.y = 0.0
It can be useful if you want to recognize if someone used MyMathLib() or MyMathLib(0.0)
That is because your __init__ requires two arguments instead of one. Instead of doing this, you can pass a default variable like #Jay Mody's answer. And also:
self == None will never be true because self always passes in a value y.
Here is another way you can do it:
class MyMathLib:
def __init__(self):
self.y = 0.0
def passNumber(y):
self.y = y
As you can see, if the number is passed using passNumber, that means that the number isn't 0.0. This is another way to do it.

How to fix "not defined", but it is defined?

I am coding something with python and I made a main class. I am working with tkinter.
In my class
class Main(tk.Tk):
I have multiple variables. There are two variables, which I defined. Underneath that, there is another variable, that runs the other two variables, I wrote above. But then it says, that those are not defined, but it is. The Error message: name 'bruteforceABC' is not defined
class Main(tk.Tk):
def bruteforceABC():
for length in range(1, 3): # only do lengths of 1 + 2
to_attempt = product(chars, repeat=length)
for attempt in to_attempt:
print(''.join(attempt))
def clear1():
list = window.grid_slaves()
for n in list:
n.destroy()
def clearforce():
bruteforceABC()
clear1()
I don't know, why it says, it is not defined. Because I've defined it. What can I do, that I don't get this error?
Thank you, for your help!
You have defined these functions as class methods but are calling them as generic ones. You should use self.method() to call them.
class Main(tk.Tk):
#staticmethod
def bruteforceABC():
for length in range(1, 3): # only do lengths of 1 + 2
to_attempt = product(chars, repeat=length)
for attempt in to_attempt:
print(''.join(attempt))
#staticmethod
def clear1():
list = window.grid_slaves()
for n in list:
n.destroy()
def clearforce(self):
self.bruteforceABC()
self.clear1()
Like this

ERROR: unbound method "method name" must be called with "Class Name" instance as first argument (got classobj instance instead)

I hope you guys can help me out here.
I've been given this error from the following code:
Traceback (most recent call last):
File "C:\Python27\Lib\idlelib\Tarea5.py", line 60, in <module>
bg.addBandit(b)
TypeError: unbound method addBandit() must be called with BanditGroup instance as first argument (got classobj instance instead)
The code:
from numpy import *
from matplotlib import pyplot as p
class Bandit:
power = random.uniform(15,46)
life = random.uniform(40,81)
def __init__(self, power, life):
self.power = power
self.life = life
class BanditGroup:
def __init__(self,a):
self.group = [a] #Where 'a' is an object of the class Bandit
def addBandit(self,b):
self.group.append(b) #Where 'b' is an object of the class Bandit
return self.group
howmanygroups = random.randint(4,11)
i = 0
j = 0
while i <= howmanygroups:
bg = BanditGroup
howmanybandits = random.randint(1,11)
while j <= howmanybandits:
b = Bandit
bg.addBandit(b) #<-- line 60
j+=1
bgposx = random.uniform(0,50000)
bgposy = random.uniform(0,50000)
p.plot(bgposx,bgposy,'r^')
i+=1
I'd really appreciate if someone could tell me what's going on here. I started learning python 2.7 about 2 months ago.
Thanks!
Try changing your code to (notice the parenthesis around class instantiation):
while i <= howmanygroups:
bg = BanditGroup(a)
howmanybandits = random.randint(1,11)
while j <= howmanybandits:
b = Bandit(power, life)
bg.addBandit(b) #<-- line 60
The problem is that addBandit requires an instance of BanditGroup to be used. Adding (...) after the class name will create one:
bg = BanditGroup(...)
Right now, you have bg pointing to the class itself, not an instance of it.
The same thing needs to be done here with Bandit:
b = Bandit(...)
Note: ... means to pass in the appropriate arguments. You made BanditGroup.__init__ with a required a parameter and Bandit.__init__ with required power and life parameters. Since I don't know what you want these to be, I left them out.
Yes probably need parens when you create an instance of your Bandit and BanditGroup classes. Otherwise, you're assigning a class to your variables, not an instance of a class.
EG: bg = BanditGroup()

Get the return value from a function in a class in Python

I am trying to simply get the value out of my class using a simple function with a return value, I'm sure its a trivial error, but im pretty new to python
I have a simply class set up like this:
class score():
#initialize the score info
def __init__(self):
self.score = 0
self.num_enemies = 5
self.num_lives = 3
# Score Info
def setScore(num):
self.score = num
# Enemy Info
def getEnemies():
return self.num_enemies
# Lives Info
def getLives():
return self.getLives
etc.....
Than I create an instance of the class as such:
scoreObj = score()
for enemies in range(0, scoreObj.getEnemies):
enemy_sprite.add(enemy())
I get the error saying that an integer is expected, but it got an instancemethod
What is the correct way to get this information?
Thanks!
scoreObj.getEnemies is a reference to the method. If you want to call it you need parentheses: scoreObj.getEnemies().
You should think about why you are using a method for this instead of just reading self.num_enemies directly. There is no need for trivial getter/setter methods like this in Python.
The first parameter for a member function in python is a reference back to the Object.
Traditionally you call it "self", but no matter what you call the first parameter, it refers back to the "self" object:
Anytime I get weird errors about the type of a parameter in python, I check to see if I forgot the self param. Been bit by this bug a few times.
class score():
#initialize the score info
def __init__(self):
self.score = 0
self.num_enemies = 5
self.num_lives = 3
# Score Info
def setScore(self, num):
self.score = num
# Enemy Info
def getEnemies(self):
return self.num_enemies
# Lives Info
def getLives(foo): #foo is still the same object as self!!
return foo.num_lives
#Works but don't do this because it is confusing
This code works:
class score():
def __init__(self):
self.score = 0
self.num_enemies = 5
self.num_lives = 3
def setScore(self, num):
self.score = num
def getEnemies(self):
return self.num_enemies
def getLives(self):
return self.getLives
scoreObj = score()
for enemy_num in range(0, scoreObj.getEnemies()):
print enemy_num
# I don't know what enemy_sprite is, but
# I commented it out and just print the enemy_num result.
# enemy_sprite.add(enemy())
Lesson Learned:
Class functions must always take one parameter, self.
That's because when you call a function within the class, you always call it with the class name as the calling object, such as:
scoreObj = score()
scoreObj.getEnemies()
Where x is the class object, which will be passed to getEnemies() as the root object, meaning the first parameter sent to the class.
Secondly, when calling functions within a class (or at all), always end with () since that's the definition of calling something in Python.
Then, ask yourself, "Why am I not fetching 'scoreObj.num_lives' just like so instead? Am I saving processing power?" Do as you choose, but it would go faster if you get the values directly from the class object, unless you want to calculate stuff at the same time. Then your logic makes perfect sense!
You made a simple mistake:
scoreObj.getEnemies()
getEnemies is a function, so call it like any other function scoreObj.getEnemies()

Call Nested Function in Python

I have a method that i have broken into smaller nested functions to break up the code base:
def foo(x,y):
def do_this(x,y):
pass
def do_that(x,y):
pass
do_this(x,y)
do_that(x,y)
return
Is there a way to run one of the nested functions by itself. eg:
foo.do_this(x,y)
EDIT:
I am trying to setup caching on a web server i have built using pyramid_breaker
def getThis(request):
def invalidate_data(getData,'long_term',search_term):
region_invalidate(getData,'long_term',search_term)
#cached_region('long_term')
def getData(search_term):
return response
search_term = request.matchdict['searchterm']
return getData(search_term)
This is my understanding may not be accurate:
Now the reason i have this is that the namespace used by the decorator to create the cache key is genereated from the function and the arguements. You can't therefore just put the decorator on getThis as the request variable is unique-ish and the cache is useless. So i created the inner function which has repeatable args (search_term).
However to invalidate the cache (ie refresh), the invalidation function requires scope to know of the 'getData' function so also needs to be nested. Therefore i need to call the nested function. You wonderful people have made it clear its not possible so is someone able to explain how i might do it with a different structure?
I assume do_this and do_that are actually dependent on some argument of foo, since otherwise you could just move them out of foo and call them directly.
I suggest reworking the whole thing as a class. Something like this:
class Foo(object):
def __init__(self, x, y):
self.x = x
self.y = y
def do_this(self):
pass
def do_that(self):
pass
def __call__(self):
self.do_this()
self.do_that()
foo = Foo(x, y)
foo()
foo.do_this()
These previous answers, telling you that you can not do this, are of course wrong.
This is python, you can do almost anything you want using some magic code magic.
We can take the first constant out of foo's function code, this will be the do_this function. We can then use this code to create a new function with it.
see https://docs.python.org/2/library/new.html for more info on new and https://docs.python.org/2/library/inspect.html for more info on how to get to internal code.
Warning: it's not because you CAN do this that you SHOULD do this,
rethinking the way you have your functions structured is the way to go, but if you want a quick and dirty hack that will probably break in the future, here you go:
import new
myfoo = new.function(foo.func_code.co_consts[1],{})
myfoo(x,y) # hooray we have a new function that does what I want
UPDATE: in python3 you can use the types module with foo.__code__:
import types
myfoo = types.FunctionType(foo.__code__.co_consts[1], {})
myfoo() # behaves like it is do_this()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: do_this() missing 2 required positional arguments: 'x' and 'y'
There is, you have to make them as an attribute of the function object. But this will work only after the first call of foo.
def foo(x,y):
def do_this(x,y):
pass
def do_that(x,y):
pass
do_this(x,y)
do_that(x,y)
foo.do_this = do_this
foo.do_that = do_that
return
>>> foo.do_this(1, 2)
AttributeError: 'function' object has no attribute 'do_this'
>>> foo(1, 2)
>>> foo.do_this(1, 2)
>>>
No (apart from poking around in closure objects, which is complete overkill here). If you need that, use a class.
class foo(object):
def do_this(self, x, y):
...
def do_that(self, x, y):
...
def do_other_stuff(self, x, y):
# or __call__, possibly
Or just put those functions in the outer scope, since you're passing everything as arguments anyway:
def foo(x, y):
do_this(x, y)
do_that(x, y)
def do_this(x, y):
...
def do_that(x, y):
...
No, there is not. Since you may access variables in an outer scope from within a nested function:
def foo(x,y):
def do_this(z):
print(x,y,z)
# ...
there is no way to call do_this while providing a binding for x and y.
If you must call do_this from elsewhere, simply make it a top level function at the same level as foo.
You can try this way:
def a(x, y):
name = 'Michael'
a.name = name
a.z = z = x * y
#a.z = z
def b():
def give_me_price(f,g):
price = f * g
return price
def two(j,k):
surname = 'Jordan' # without return surname give None
# two = two('arg1', 'arg2')
# b.blabla = two
one = give_me_price(5, 10)
b.halabala = one
print(a.name) # ;)
x = 20
y = 30
a(x,y) # IMPORTANT! first you must run function
print(a.z)
print(a.name * 5)
print('-'*12)
b() # IMPORTANT! first you must run function
print('price is: ' + str(b.give_me_price(5, 25)))
# print(b.blabla)
This is how I did it.
CODE
def getMessage(a="", b="", c=""):
def getErrorMessage(aa, bb):
return "Error Message with/without params: {}{}".format(aa, bb)
def getSuccessMessage(bb, cc):
return "Success Message with/without params: {}{}".format(bb, cc)
def getWarningMessage(aa, cc):
return "Warning Message with/without params: {}{}".format(aa, cc)
return {
"getErrorMessage": getErrorMessage(a, b),
"getSuccessMessage": getSuccessMessage(b, c),
"getWarningMessage": getWarningMessage(a, c),
}
a = "hello"
b = " World"
c = "!"
print(getMessage(a, b)["getErrorMessage"])
print(getMessage(b=b, c=c)["getSuccessMessage"])
print(getMessage(a=a, c=c)["getWarningMessage"])
print(getMessage(c=c)["getWarningMessage"])
OUTPUT
Error Message with/without params: hello World
Success Message with/without params: World!
Warning Message with/without params: hello!
Warning Message with/without params: !

Categories

Resources