Python - can call same class twice(or more) in thread? - python-3.x

I don't very understand the classes logic in python but cannot answer on web.
I have create a class to generate person info:
class person:
def fristnameGen(gender):
...
def emailGen(firstname,surname):
...
i create a bot to call it like this:
from person import *
class bots:
def __init__(self):
self.person = person()
def createDB(self):
print(self.person.name)
#do something...
finally i call it by a button with thread
from bots import *
import threading
class Panel:
def __init__(self):
self.top = tk.Tk()
self.bot = bots()
self.buildUI()
def foo(self):
self.bot.createDB(self.stringPhone.get())
def threadTheAction(func, *args):
t = threading.Thread(target=func, args=args)
t.setDaemon(True)
t.start()
def buildUI(self):
Button = tk.Button(self.top, text ="Start", command = lambda :self.threadTheAction(self.foo))
I get this error:
TypeError: 'Panel' object is not callable
However, i call it directly, its work
Button = tk.Button(self.top, text ="Start", command = lambda :self.foo())
How to fix the error?
...
2. Moreover, i tried create p1 = person() and p2= person() and print it. Found p1 and p2 is a same person, i prefer each new a class have a new one. How to generate "new person" using classes?
Thank you

You seem to have a lot of confusion about Object Oriented Programming in Python. Some of your methods have self parameters and some do not, seemingly at random. That's the source of your current error.
The threadTheAction method in your Panel class is getting the Panel instance passed in as its first argument, but that's named func in the method (since you omitted self). The real function you're passing as an argument gets caught in the variable argument *args. When the thread tries unsuccessfully to call it, you get an exception. Adding self before func would fix the immediate problem:
def threadTheAction(self, func, *args):
I suspect if your code got further along, you'd run into other errors with other methods without self in their parameter lists. For instance, none of the methods you've shown in person are likely to work correctly.
As for your second question, you haven't shown enough of person to know what's happening, but you're probably doing instance variables wrong somehow. With no self parameter in the methods, that's almost inevitable (since you assign to self.whatever to set a whatever attribute on the current instance). If you need help squaring that away, I suggest you ask a separate question (Stack Overflow is best when each question is self-contained) and provide the full code for your person class.

Related

Trying to figure out how to pass variables from one class to another in python while calling a class from a dictionary

So I am getting used to working with OOP in python, it has been a bumpy road but so far things seem to be working. I have, however hit a snag and i cannot seem to figure this out. here is the premise.
I call a class and pass 2 variables to it, a report and location. From there, I need to take the location variable, pass it to a database and get a list of filters it is supposed to run through, and this is done through a dictionary call. Finally, once that dictionary call happens, i need to take that report and run it through the filters. here is the code i have.
class Filters(object):
def __init__ (self, report, location):
self.report = report
self.location = location
def get_location(self):
return self.location
def run(self):
cursor = con.cursor()
filters = cursor.execute(filterqry).fetchall()
for i in filters:
f = ReportFilters.fd.get(i[0])
f.run()
cursor.close()
class Filter1(Filters):
def __init__(self):
self.f1 = None
''' here is where i tried super() and Filters.__init__.() etc.... but couldn't make it work'''
def run(self):
'''Here is where i want to run the filters but as of now i am trying to print out the
location and the report to see if it gets the variables.'''
print(Filters.get_location())
class ReportFilters(Filters):
fd = {
'filter_1': Filter1(),
'filter_2': Filter2(),
'filter_3': Filter3()
}
My errors come from the dictionary call, as when i tried to call it as it is asking for the report and location variables.
Hope this is clear enough for you to help out with, as always it is duly appreciated.
DamnGroundHog
The call to its parent class should be defined inside the init function and you should pass the arguments 'self', 'report' and 'location' into init() and Filters.init() call to parent class so that it can find those variables.
If the error is in the Filters1 class object, when you try to use run method and you do not see a location or a report variable passed in from parent class, that is because you haven't defined them when you instantiated those object in ReportFilters.fd
It should be:
class ReportFilters(Filters):
fd = {
'filter_1': Filter1(report1, location1),
'filter_2': Filter2(report2, location2),
'filter_3': Filter3(report3, location3)
}
class Filter1(Filters):
def __init__(self, report, location):
Filters.__init__(self, report, location)
self.f1 = None
def run(self):
print(self.get_location())

Adding Parameters to init function of inherited class

i am quite new to inheritance and overriding methods and i am not quite sure how to override the __init__ method of a class, more specifically, adding another parameter to it.
Basically i want to override the __init__ method of the tkinter class simpledialog.Dialog.
From the documentation the init method of simpledialog.Dialog has the Parameters __init__(self,parent,title=None) and i want it to be __init__(self,parent,labeltitle,title=None)
Ok guys, so for context i also changed some of the other methods of the class, i will give you the code so that people know why i want labeltitle in the init method. I found a solution on how to solve my problem, if anyone has an idea or sees a problem with this let me know.
import tkinter
from tkinter import simpledialog
class MyDialog(simpledialog.Dialog):
def __init__(self,parent,labeltitle,title):
self.labeltitle=labeltitle
super().__init__(parent,title)
def body(self, master):
self.geometry("400x300")
tkinter.Label(master, text=self.labeltitle).grid(row=0)
self.e1 = tkinter.Entry(master)
self.e1.grid(row=0, column=1,pady=30)
return self.e1 # initial focus
def apply(self):
first = self.e1.get()
self.result = first
so now when i create an Object of MyDialog like this:
asd = MyDialog(root,"title_of_the_label","title_of_the_Dialogwindow")
i get the Dialogwindow with these titles. Now i can create multiple objects with different windowtitles and labeltitles, since the simpledialog.Dialog class only allowed to change the title of the Dialogwindow, not the labeltitle.

How do I bind to a function inside a class and still use the event variable?

class Player():
def __init__():
...
def moveHandle(self, event):
self.anything = ...
box.bind("<Key>", Player.moveHandle)
The bind function sets self as the event variable and ignores/throws up an error for event. I can't find a way to pass the event argument to the correct variable and maintain self for that function, even if I use args*. I can do one or the other, but not both.
I'm probably just lacking some basic knowledge about classes to be honest, I taught them to myself and didn't do it very thoroughly.
If I made a syntax mistake, it's because of me rewriting out the code incorrectly; in my program, the code works until the variables get passed.
the problem is that you are trying to use an instance method as a class method.
consider the following:
class Player():
def __init__():
...
def moveHandle(self, event):
self.anything = ...
box.bind("<Key>", Player.moveHandle)
where box is an instance of something, but Player is not.
instead this:
class Player():
def __init__(self):
...
def moveHandle(self, event):
self.anything = ...
p = Player()
box.bind("<Key>", p.moveHandle)
creates an instance of the player class, and then binds to the instances method, not the class method.

Passing a Function as a Parameter for a Class, eventually turning it into a method

Sorry if the title is confusing. I'm writing a minimalist game engine, and trying to define a class called "Area" where if the player enters the area, a function defined by the user happens. For example, one could create an instance
Area(location,function) that would fire function on the player when the player enters location (for the sake of simplicity, let it be a point or something).
Note: in pseudo-python
# in init.py
...
def function(player):
kill player
deathZone = Area(location,function)
--------------------------------------
# in player.update()
...
for area on screen:
if player in area:
Area.function(player)
The point of this is that the developer (aka me) can use any function they choose for the area. Is there anyway to do this, or should I try a better approach?
Sure, this kind of thing is certainly possible. In python, everything is an object, even a function. So you can pass around a function reference as a variable. For example try the following code:
import math
def rectangle(a, b):
return a*b
def circle(radius):
return math.pi * radius**2
class FunctionRunner(object):
def __init__(self):
self.userFunction = None
self.userParams = None
def setUserFunction(self, func, *params):
self.userFunction = func
self.userParams = params
def runFunction(self):
return self.userFunction(*self.userParams)
if __name__ == '__main__':
functionRunner = FunctionRunner()
functionRunner.setUserFunction(rectangle, 6, 7)
print(functionRunner.runFunction())
functionRunner.setUserFunction(circle, 42)
print(functionRunner.runFunction())
Here you have two functions that are defined for an area, and a class called FunctionRunner which can run any function with any number of input arguments. In the main program, notice that you need only pass the reference to the function name, and any input arguments needed to the setUserFunction method. This kind of thing will allow you to execute arbitrary code on the fly.
Alternatively, you could also replace a method on your class with a reference to another function (which is what you are asking), though this seems less safe to me. But it is certainly possible. For example you could have a class like this:
class FunctionRunner2(object):
def __init__(self):
pass
def setUserFunction(self, func):
self.theFunction = func
def theFunction(self, *params):
pass
And then do this:
if __name__ == '__main__':
functionRunner2 = FunctionRunner2()
functionRunner2.setUserFunction(rectangle)
print(functionRunner2.theFunction(6,7))
functionRunner2.setUserFunction(circle)
print(functionRunner2.theFunction(42))

Passing StringVar object from Entry to Label within functions in tkinter

Hi I've been struggling to get this to work, each time i change something I receive another error. I've been trying to create an entry box with a function and then get the variable from the entry box into a label, created by a button press. When I tried to do this often this error came up.
TypeError: get() missing 1 required positional argument: 'self'
I then put self in in the method brackets.
command = lambda: x.myFunc(self.my_variable.get(self))
Then another error, which I'm not sure how to sort out.
AttributeError: 'My_Class' object has no attribute '_tk'
Here's the full code, I'm new to classes and self, so any corrections are welcome.
from tkinter import *
import time
class My_Class:
def start(self):
self.root=Tk()
self.my_variable=StringVar
self.entry_box=Entry(self.root, textvariable=self.my_variable)
self.entry_box.pack()
self.button=Button(self.root,text="Pass variable now",
command=lambda:x.myFunc(self.my_variable.get(self)))
self.button.pack()
def myFunc(self,my_variable):
self.lab=Label(self.root,text=self.my_variable)
self.lab.pack()
x=My_Class()
x.start()
This is the correct way to create a StringVar object:
text = StringVar() # note additional ()
Can you explain me what x is in the following statement:
lambda: x.myFunc(self.my_variable.get(self))
x is not visible inside the class, because it's declared outside the class.
myFunc is not indented correctly: you should indent it like the __init__ method.
I really recommend you to watch some tutorials on OOP before proceeding. You are basically trying to guess how OOP works.
If you make myFunc A method if the class (which you might be trying to do; it's hard to know because your indentation is wrong), you don't have to pass anything to myFunc. That function has access to everything in the class, so it can get what it needs, when it needs it. That lets you eliminate the use of lambda, which helps reduce complexity.
Also, you normally don't need a StringVar at all, it's just one more thing to keep track of. However, if you really need the label and entry to show exactly the same data, have them share the same textvariable and the text is updated automatically without you having to call a function, or get the value from the widget, or set the value n the label.
Here's an example without using StringVar:
class My_Class:
def start(self):
...
self.entry_box = Entry(self.root)
self.button = Button(..., command = self.myFunc)
...
def myFunc(self):
s = self.entry_box.get()
self.lab = Label(..., text = s)
...

Resources