Returning values from callback(s) in Python - python

I am currently looking at trying to use a callback in Python.
What I would like to do is return a value from the callback and then use this return value for conditional processing. So for example if the user enters "Y" I would like to print something to the console.
As I am new to Python the code below is as close as I can get currently but:
a) I am not sure if it is the Pythonic way of doing it
b) the correct way of doing it?
class Observable:
def subscribe(self,callback):
self.callback = callback
def fire(self):
self.callback()
class CallBackStuff:
def doCallback(self):
userInput = raw_input("Please enter Y or N?")
return userInput
if __name__ == '__main__':
s = CallBackStuff()
o = Observable()
o.subscribe(s.doCallback)
t = o.fire()
print t

The easiest way I can think of to do this in your code is to just store the input as
a variable in the CallBackStuff object. Then after you've called the call-back function, you can just access the input data from the CallBackStuff instance. Example below.
class Observable:
def subscribe(self,callback):
self.callback = callback
def fire(self):
self.callback()
class CallBackStuff:
storedInput = None # Class member to store the input
def doCallback(self):
self.storedInput = raw_input("Please enter Y or N?")
if __name__ == '__main__':
s = CallBackStuff()
o = Observable()
o.subscribe(s.doCallback)
o.fire()
print s.storedInput # Print stored input from call-back object

class Observable(object):
def __call__(self, fun):
return fun()
class Callback(object):
def docallback(self):
inp = raw_input()
return inp
if __name__ == "__main__":
print Observable()(Callback().docallback)

Related

Method declared but not found in a class object

I just began the long and painful journey in Python Class Objects and try this:
class UgcObject:
def __init__(self, strPlateformeOld, strIdOld):
self.strPlateformeOld = strPlateformeOld
self.strIdOld = strIdOld
def GetApiUpdatedMetadata(self):
if self.strPlateforme == "youtube":
return True
def GetblnUpdatePossible(self):
return GetApiUpdatedMetadata()
if __name__ == '__main__':
ugc_test = UgcObject("youtube","id")
print(ugc_test.GetblnUpdatePossible())
I got an error message: NameError: name 'GetApiUpdatedMetadata' is not defined
I don't get why considering that I believe the GetApiUpdatedMetadata is declared and above the method that calls it.
What did I did wrong?
If you are trying to call another method in the same class it should have self. in front of it, and the variable name self.strPlateforme is wrong:
class UgcObject:
def __init__(self, strPlateformeOld, strIdOld):
self.strPlateformeOld = strPlateformeOld
self.strIdOld = strIdOld
def GetApiUpdatedMetadata(self):
if self.strPlateformeOld == "youtube":
return True
def GetblnUpdatePossible(self):
return self.GetApiUpdatedMetadata()
if __name__ == '__main__':
ugc_test = UgcObject("youtube","id")
print(ugc_test.GetblnUpdatePossible())

"AttributeError: 'list' object has no attribute 'SMSMessage'"

I have tried many ways but can't seem to get the length of my list through the method in my class my code:
SMSStore = []
unreadMessage = []
class SMSMessage(object):
def __init__(self, hasBeenRead, messageText, fromNumber):
self.hasBeenRead = hasBeenRead
self.messageText = messageText
self.fromNumber = fromNumber
hasBeenRead = False
def markAsRead(self, hasBeenRead):
hasBeenRead = True
def add_sms(self):
newMessage = (self.hasBeenRead, self.messageText, self.fromNumber)
return SMSStore.append(newMessage)
def get_count():
return len(SMSStore)
def get_message(self, i):
hasBeenRead = True
return SMSStore[i][1]
def get_unread_messages(i):
for i in SMSStore:
if SMSStore[i][0] == False:
unreadMessage.append(SMSStore[i])
print unreadMessage
def remove(self, i):
return SMSStore.remove(i)
This is how a message in the list would ideally look like:
#sample = SMSMessage(False, "Hello friend!", 0742017560)
And here is how the class is used
userChoice = ""
while userChoice != "quit":
userChoice = raw_input("What would you like to do - read/send/quit?")
if userChoice == "read":
print len(SMSStore)#this way i can get the length of the list anyway without using get_count
SMSStore(get_count()
unreadChoice = raw_input("Would you like to retrieve all unread messages or one of your own choice? - all unread/custom ")
if unreadChoice == "custom":
i = int(raw_input("Please enter which message number you want to read: "))
print get_message(i) #I dont understand how i works and how to get it working with the object definition
elif userChoice == "send":
messageText = raw_input("Please type in your message: ")
fromNumber = raw_input("Please type in the number it was sent from ")
newObject = SMSMessage(False, messageText, fromNumber)
newObject.add_sms()
print SMSStore
elif userChoice == "quit":
print "Goodbye"
else:
print "Oops - incorrect input"
I can just use len(SMSStore) but I want to be able to use the method inside the class to get it. Can point out any mistakes?
This was the question asked:
Open the file called​  sms.py​
Create a class definition for an SMSMessage which has three variables:
hasBeenRead, messageText, and fromNumber. 
The constructor should initialise the sender’s number. 
The constructor should also initialise hasBeenRead  to false
Create a method in this class called MarkAsRead which should change hasBeenRead to true.
Create a list called SMSStore to be used as the inbox.
Then create the following methods:
add_sms - which takes in the text and number from the received sms to
make a new SMSMessage object. 
get_count - returns the number of messages in the store.
get_message - returns the text of a message in the list.Forthis, allow the
user to input an index i.e. GetMessage(i) returns the message
stored at position i in the list. Once this has been done,
hasBeenRead should now be true. 
get_unread_messages - should return a list of all the messages which
haven’t been read. 
remove - removes a message in the SMSStore. 
Now that you have these set up, let’s get everything working! 
in your SMSMessage class
def get_count(self, *args):
return len(SMSStore)
in your script
# create instance
sms_msg = SMSMessage() # init arg needed
print sms_msg.get_count()
SMSStore is a global variable, you could remove get_count from SMSMessage scope
SMSStore = []
unreadMessage = []
class SMSMessage(object):
...functions...
def get_count(*args):
return len(SMSStore)
and call it regularly OR
ls = range(20)
class A(object):
# declare default value for your arguments
def __init__(self, hasBeenRead = False, messageText = "", fromNumber=0):
self.a = a
self.b = b
#using classmethod
#classmethod
def get_count(cls, *args):
return len(ls)
print A.get_count()

Access "a method of a class" in "a function of another python file" by passing the class as that function's parameter

I have a class file. Let's call it "C1.py". The sample code looks like below.
class C1(object):
def __init__(self):
self.greeting = "Hello, world!"
def M1(ans):
if ans == 1 or ans == 2:
return True
else:
return False
Now, I have another python file in the same folder, which will access the class file shown above.
from trial import C1
def getAns(class1):
while True:
ans = input("Answer: ")
if class1.M1(ans):
return ans
break
sample = C1()
print sample.greeting
ans = getAns(sample)
print ans
When I run those files, sample.greeting prints fine. Everything is fine until when the execution reaches the line "ans = getAns(C1)", which gives the error "M1() takes exactly 1 argument (2 given)".
So, where in the code should I change so that I can call that method successfully?
Note here that the above code is only the abstraction of my whole program to highlight my problem. It sounds stupid with just the code above alone. So, please, please bear with that for me.
M1 is currently defined as a method of C1, as such it needs to have an additional self argument which would be the instance of the class. I.e
class C1(object):
def __init__(self):
self.greeting = "Hello, world!"
def M1(self, ans):
if ans == 1 or ans == 2:
return True
else:
return False
In other languages such as C++ or Java the presence of self (or this) is implicit, but in python it's explicit.
alternatively if you don't want or need M1 to access C1's state you could make M1 static via #staticmethod i.e.
class C1(object):
def __init__(self):
self.greeting = "Hello, world!"
#staticmethod
def M1(ans):
if ans == 1 or ans == 2:
return True
else:
return False

python accessing another function variable error

I am trying to get input from one function and dispaying it in another function but i could not get the expected result
class Base(object):
def user_selection(self):
self.usr_input = input("Enter any choice")
user_input = self.usr_input
return user_input
def switch_selection(user_input):
print user_input
b = Base()
b.user_selection()
b.switch_selection()
When i execute this program i get
Enter any choice1
<__main__.Base object at 0x7fd622f1d850>
I should get the value which i entered but i get
<__main__.Base object at 0x7fd622f1d850>
How could i get the value which i entered?
def switch_selection(user_input):
print user_input
..
b.switch_selection()
You may notice that you're not passing any argument into switch_selection when calling it, yet you're expecting to receive one argument. That's something of a cognitive disconnect there. You happen to actually receive an argument though, which is b. An object method in Python receives its object instance as its first parameter. The argument you're receiving is not user_input, it's self. That's what you're printing, that's the output you're seeing.
Two possibilities to fix this:
class Base(object):
def user_selection(self):
self.user_input = input("Enter any choice")
def switch_selection(self):
print self.user_input
or:
class Base(object):
def user_selection(self):
return input("Enter any choice")
def switch_selection(self, user_input):
print user_input
b = Base()
input = b.user_selection()
b.switch_selection(input)
Try this Code Working perfect for me,
class Base(object):
def user_selection(self):
self.usr_input = input("Enter any choice")
user_input = self.usr_input
return user_input
def switch_selection(self,user_input):
print user_input
b = Base()
g=b.user_selection()
b.switch_selection(g)

Calling functions from main python

I have some python 3.4 code that works fine:
def run():
m = 0
while m != 1:
p = input('Please choose p: ')
p = makeInt(p)
#Some other code
print(p)
m = makeInt(input('Enter 1 if you would like to quit: '))
def makeInt(i):
try:
i = int(i)
except ValueError:
i = input('Incorrect input! Enter your answer: ')
i = makeInt(i)
return i
#Some other functions
if __name__ == '__main__':
run()
I want to put all this code in a class (Except possibly if __name__ ==...) When I put all the code including if __name__ ==... in a class like so:
class Foo(object):
def run(self):
m = 0
while m != 1:
p1 = input('Please choose p: ')
p1 = self.makeInt(p1)
#Some other code
print(p1)
m = self.makeInt(input('Enter 1 if you would like to quit: '))
def makeInt(self, i):
try:
i = int(i)
except ValueError:
i = input('Incorrect input! Enter your answer: ')
i = self.makeInt(i)
return i
#Some other functions and stuff
if __name__ == '__main__':
run()
I get the following error: TypeError: run() missing 1 required positional argument: 'self'. When I remove the self argument from run() it runs until makeInt() is called and then I get: NameError: name 'makeInt' is not defined. I get the same error if I take the if statement out of the class and call Foo.run(). I have some other code earlier in this program that works when I call functions of a class from another function in that same class. I realize I don't have to put all my code in a class, but in this case I want to. Why am I getting these errors and what can I do to put my working code in a class?
As others mentioned, by putting your functions in a class, you've made them methods, that means they need an instance of this class as first argument. So you can indeed call your run method using Foo().run() as Foo() will create an instance of Foo.
Another way (e.g. if you don't need the class for anything else than encapsulation) is to make them static, using the staticmethod decorator:
class Foo(object):
#staticmethod
def run():
...
#staticmethod
def makeInt(i):
...
if __name__ == '__main__':
Foo.run() # don't need an instance as run is static
In Python, a method can be static, i.e. no need for any special argument, a class method, i.e. first argument is the class itself, or a standard method, i.e. the first argument is an instance of the class.
Since you wrap your code within a class, your run() is a method now. You should remove your main from your class by unindenting it and initialize an instance of your class:
if __name__ == '__main__':
Foo().run()
It thinks the guard is a part of your class due to the indentation: you have your guard indented to the same level as the other class members. Unindent the
if __name__ == '__main__'
Also change it to be
if __name__ == '__main__':
main()
and then instantiate a new object of type Foo in your newly created main() function
def main():
newFoo = Foo()
newFoo.run()

Categories

Resources