Object with multiple functions with optional arguments in another thread - multithreading

I have a worker object, which has many functions and I'll like to use them on an extra thread. So, I followed this answer and it works if I pass a fixed number of arguments to the functions, more or less like this:
_signalCommand = QtCore.pyqtSignal(str, str)
self._signalCommand.connect(self.nanomax.test)
self._signalCommand.emit('testA', 'testB')
But in my case, I can't use a fixed number of arguments. I need optional ones, my functions are like this:
def test(self, test1='test1', test2='test2'):
print test1
print test2
So, in order to fix that I was using lambda, like this:
_signalCommand = QtCore.pyqtSignal()
self._signalCommand.connect(lambda: self.nanomax.test('testA', 'testB')
self._signalCommand.emit()
Doing this way, indeed, fix my optional arguments problems but it makes the object running in the main thread. I think this is because lambda creates another function and is like calling the worker directly (self.nanomax.test('testA', 'testB') as mentioned in the answer I previously shared.
Is there anyway to avoid this? Thank you in advance.

You could probably use partial for this
eg :
from functools import partial
...
_signalCommand = QtCore.pyqtSignal()
self._signalCommand.connect(partial(self.nanomax.test, 'testA', 'testB'))
self._signalCommand.emit()

Related

tkinter: How to pass arguments when <<ComboboxSelected>> is bound to a method?

I am a newbie with the tkinter library and I don't understand how to pass arguments from a combobox to a method I would like to bind on event action?
Example:
class Controller():
def __init__(self):
self.root = tk.Tk()
self.view = View(self.root)
self.view.sidepanel.motor_sel_combo.bind("<<ComboboxSelected>>", lambda event, arg=self.view.sidepanel.motor_sel_combo.get(): self.motor_selection(event, arg))
def motor_selection(self,event, mot_selected):
#print(event) #--> would only print <VirtualEvent event x=0 y=0> #????
#print(event.widget.get())
print(mot_selected)
The output for print(mot_selected) is empty. The tkinter manual does not show a good example.
self.view.sidepanel.motor_sel_combo.get() contains the imho the selected value of the combobox.
I tried as well with functools.partial instead of lambda, but I don't get it to work.
Could you show me the correct syntax with lambda and functools.partial, please?
Thank you.
You're calling self.view.sidepanel.motor_sel_combo.get() at the time you create the lambda, not at the time the combobox value has changed.
You should call the get() method inside the function instead of trying to pass it to the function. The use of lambda here does nothing but make the code unnecessarily complex.
class Controller():
def __init__(self):
self.root = tk.Tk()
self.view = View(self.root)
self.view.sidepanel.motor_sel_combo.bind("<<ComboboxSelected>>",
self.motor_selection)
def motor_selection(self,event):
mot_selected = self.view.sidepanel.motor_sel_combo.get()
...
It was pointed out in a comment by #acw1668 that the function should use event.widget.get() instead of self.view.sidepanel.motor_sel_combo.bet() and that is true. Since we want to call get() on the widget that was bound, using the shorter version is the better solution. It is better for two reasons: because it makes the function loosely coupled to the other code, and because it makes it more clear that the function is operating on the widget it was bound to. That means that the other code could rename that variable and the function will continue to work without having to also be modified.
For such a small program, whether the function is loosely coupled or tightly coupled isn't that big of a deal. I would argue, though, that using event.widget in a callback is a best practice that one should get in the habit of doing.
The OP indicated in comments they want to see a version that uses lambda. I don't recommend it, but the root of the problem with lambda is that the OP was calling the get() method when defining the lambda rather than when it is called. To call the get() method when the lambda runs, the call must be moved inside the body:
self.view.sidepanel.motor_sel_combo.bind(
"<<ComboboxSelected>>",
lambda event: self.motor_selection(event, self.view.sidepanel.motor_sel_combo.get())
)
In this case, motor_selection must be like in the OP's original code and accept two parameters.

Building a good class method

I've built a class to ask a user a question, based on a type.
class Question:
def __init__(self, subject):
self.subject = subject
self.question = f"Enter the {subject} to be created. You may end this by typing 'DONE':\n"
self.still_needed = True
def ask_question(self):
ans_list = []
running = True
while running:
var = input(f"Enter {self.subject}?\n")
if var.lower() == 'done':
running = False
else:
ans_list.append(var)
return ans_list
The idea is to have a question model, to create lists of items.
This seems to work well with the following code in main.
roles = Question(subject="role").ask_question()
This creates a list from the Queue Class and uses it's method ask question to generate the list. As far as I can tell the object is then destroyed, as it's not saved to a variable.
My question, being new to Python and OOP is, does this seem like a solid and non-confusing way, or should I refractor? If so, what does the community suggest?
MY OPINION
I guess it depends on you. For one, one of the main purposes of using a class is to create an instance with it later on. Classes are objects ,or "categories" as I like to call them, that you use when there are distinctive types of instances in your project.
Given your code snippet, I can't really suggest anything, I don't know the usage of self.question and self.still_needed. However, if I were to base my opinion on just this part: roles = Question(subject="role").ask_question(), then I'd definitely go with using a function instead. As you've said,
As far as I can tell the object is then destroyed, as it's not saved
to a variable.
ALTERNATIVE SOLUTION
Use decorators → the one with # symbol
In this case, #staticmethod is the way to go!
What are staticmethods? The staticmethod decorator is a way to create a function in a class. So instead of it becoming a method, it can be treated as a function (without self parameter). This also means that a static method bounds to the class rather than its object. Consequently, static methods do not depend on objects (hence, you don't need to create an object for you to use it). Example:
class SomeMathStuff():
#staticmethod
def AddSomeNumbers(iterable):
return sum(iterable)
result = SomeMathStuff.AddSomeNumbers([1, 2, 3])
# result = 6
As you can see, I did not need to create an object, instead I just needed to call its class to use it. Word of warning, most Python programmers argue that this is the un-Pythonic way, but I wouldn't worry too much about it. Hell, even I use these methods sometimes. In my defense, this is a good and efficient way to organize your project. With this, you can apply class methods globally and you can "categorize" them in certain classes you find suitable.
Anyway, this is all I have! I apologize if I misinformed you in any way.
ADDITIONAL INFROMATION ... in case I wasn't the best teacher
https://www.programiz.com/python-programming/methods/built-in/staticmethod
Difference between staticmethod and classmethod
https://softwareengineering.stackexchange.com/questions/171296/staticmethod-vs-module-level-function

How to bypass a function with #functools.lru_cache decorator

Hope you are doing well!
I'm using a function that is utilizing the lru_cache of functools library. for example:
#functools.lru_cache(maxsize=pow(2,13))
def get_id(word):
# retrieving id, using cache if possible
I would like on some occasions to bypass the cache, thus getting the ID straight from the source,
but I wouldn't like to create 2 separate functions (one with cache, and the other without) that are running exactly the same code.
Reading the documentation of functools on docs.python I understand that the cache can be bypassed:
The original underlying function is accessible through the wrapped
attribute. This is useful for introspection, for bypassing the cache,
or for rewrapping the function with a different cache.
I've tried doing so with a wrapper function, but since the inner function exists only while the outer function was running, the cache was reset on every call.
I would appreciate any help on the matter.
what the documentation is telling you is that you can access the wrapped function directly this way (bypassing the caching):
get_id.__wrapped__(word="hello")
you could add one additional layer with a flag:
from functools import lru_cache
#lru_cache(maxsize=pow(2, 13))
def get_cached(word):
return get_raw(word)
def get_raw(word):
# your logic goes here...
pass
def get_id(word, cached=True):
if cached:
return get_cached(word)
else:
return get_raw(word)

Is the `def` keyword optional? If so, why use it?

I am aware that a variable can be dynamically typed with the def keyword in Groovy. But I have also noticed that in some circumstances it can be left out, such as when defining method parameters, eg func(p1, p2) instead of func(def p1, def p2). The latter form is discouraged.
I have noticed that this is extendable to all code - anytime you want to define a variable and set its value, eg var = 2 the def keyword can be safely left out. It only appears to be required if not instantiating the variable on creation, ie. def var1 so that it can be instantiated as a NullObject.
Is this the only time def is useful? Can it be safely left out in all other declarations, for example, of classes and methods?
Short answer: you can't. There are some use cases where skipping the type declaration (or def keyword) works, but it is not a general rule. For instance, Groovy scripts allow you to use variables without specific type declaration, e.g.
x = 10
However, it works because groovy.lang.Script class implements getProperty and setProperty methods that get triggered when you access a missing property. In this case, such a variable is promoted to be a global binding, not a local variable. If you try to do the same on any other class that does not implement those methods, you will end up getting groovy.lang.MissingPropertyException.
Skipping types in a method declaration is supported, both in dynamically compiled and statically compiled Groovy. But is it useful? It depends. In most cases, it's much better to declare the type for a better readability and documentation purpose. I would not recommend doing it in the public API - the user of your API will see Object type, while you may expect some specific type. It shows that this may work if your intention is to receive any object, no matter what is its specific type. (E.g. a method like dump(obj) could work like that.)
And last but not least, there is a way to skip type declaration in any context. You can use a final keyword for that.
class Foo {
final id = 1
void bar(final name) {
final greet = "Hello, "
println greet + name + "!"
}
}
This way you can get a code that compiles with dynamic compilation, as well as with static compilation enabled. Of course, using final keyword prevents you from re-assigning the variable, but for the compiler, this is enough information to infer the proper type.
For more information, you can check a similar question that was asked on SO some time ago: Groovy: "def" keyword vs concrete type
in Groovy it plays an important role in Global and Local variable
if the variable name is same with and without def
def is considered local and without def its global
I have explained here in detail https://stackoverflow.com/a/45994227/2986279
So if someone use with and without it will make a difference and can change things.

Passing parameter to inner function in Python

While learning scopes in python, I come across the below simple code. My doubt is how can I pass the parameter to outer_var and inner_var in the function.
def outerfunc(outer_var):
def innerfunc(inner_var):
return outer_var * inner_var
return innerfunc
Basically, yeah, it's like #jonrsharpe said: it's because of closures.
Closures "close" around the state within a function that can be used later. Every time you run outerfunc(), the code will define a new version of innerfunc() that has access to outer_var that was passed in that time.
Closures are what make parameterized decorators work.

Resources