How to dynamically rewrite code of class method? - python

I am trying to optimize code that was originally written using namedtuples and function to modify them.
Each function would be called a great number of time for various values of the same namedtuple type.
Basic example would be:
def modifyTuple(record):
if record.field1 == True:
record.field2 = "VALUE1"
elif record.field3 == "SPECIAL":
record.field2 = "VALUE2"
The analysis of the bottleneck which i was experiencing and it shows that using multiple dictionary lookups every time the function is called leads to lost time. I am now trying to rewrite functions on-the-fly using inspect and basic string replacements, based on simple lists and a map from field names to fields indices.
def modifyTuple(record):
if record[0] == True:
record[1] = "VALUE1"
elif record[2] == "SPECIAL":
record[3] = "VALUE2"
This code is generated and used (i have a function which returns the modified transformation function, after internally redefining and compiling it using exec). It seems to work well, but i can't seem to find a way to deal with the case when the function actually is a class method, and therefore has a complementary "self" argument.
How should this be dealt with ? Any ideas ?

Related

Can you call/use a function returned from a list in Python?

I'm trying to store a function in a list, retrieve the function from the list later, and then call on that function. This is basically what I want to do, without any specifics. It doesn't show my purpose, but it's the same issue.
elements: list = [] # List meant to contain a tuple with the name of the item and the function of the item.
def quit_code():
exit()
element.append(("quit", quit_code))
Now, somewhere else in the code, I want to be able to use an if statement to check the name of the item and, if it's the right one at that time, run the function.
user_input = "quit" # For brevity, I'm just writing this. Let's just imagine the user actually typed this.
if elements[0][0] == user_input:
#This is the part I don't understand so I'm just going to make up some syntax.
run_method(elements[0][1])
The method run_method that I arbitrarily made is the issue. I need a way to run the method returned by elements[0][1], which is the quit_code method. I don't need an alternative solution to this example because I just made it up to display what I want to do. If I have a function or object that contains a function, how can I run that function.
(In the most simplified way I can word it) If I have object_a (for me it's a tuple) that contains str_1 and fun_b, how can I run fun_b from the object.
To expand on this a little more, the reason I can't just directly call the function is because in my program, the function gets put into the tuple via user input and is created locally and then stored in the tuple.
__list_of_stuff: list = []
def add_to_list(name, function):
__list_of_stuff.append((name, function))
And then somewhere else
def example_init_method():
def stop_code():
exit()
add_to_list("QUIT", stop_code())
Now notice that I can't access the stop_code method anywhere else in the code unless I use it through the __list_of_stuff object.
Finally, It would be nice to not have to make a function for the input. By this, I mean directly inserting code into the parameter without creating a local function like stop_code. I don't know how to do this though.
Python treats functions as first-class citizens. As such, you can do things like:
def some_function():
# do something
pass
x = some_function
x()
Since you are storing functions and binding each function with a word (key), the best approach would be a dictionary. Your example could be like this:
def quit_code():
exit()
operations = dict(quit=quit_code)
operations['quit']()
A dictionary relates a value with a key. The only rule is the key must be immutable. That means numbers, strings, tuples and other immutable objects.
To create a dictionary, you can use { and }. And to get a value by its key, use [ and ]:
my_dictionary = { 'a' : 1, 'b' : 10 }
print(my_dictionary['a']) # It will print 1
You can also create a dictionary with dict, like so:
my_dictionary = dict(a=1, b=10)
However this only works for string keys.
But considering you are using quit_code to encapsulate the exit call, why not using exit directly?
operations = dict(quit=exit)
operations['quit']()
If dictionaries aren't an option, you could still use lists and tuples:
operations = [('quit',exit)]
for key, fun in operations:
if key == 'quit':
fun()

Too many if statements

I have some topic to discuss. I have a fragment of code with 24 ifs/elifs. Operation is my own class that represents functionality similar to Enum. Here is a fragment of code:
if operation == Operation.START:
strategy = strategy_objects.StartObject()
elif operation == Operation.STOP:
strategy = strategy_objects.StopObject()
elif operation == Operation.STATUS:
strategy = strategy_objects.StatusObject()
(...)
I have concerns from readability point of view. Is is better to change it into 24 classes and use polymorphism? I am not convinced that it will make my code maintainable... From one hand those ifs are pretty clear and it shouldn't be hard to follow, on the other hand there are too many ifs.
My question is rather general, however I'm writing code in Python so I cannot use constructions like switch.
What do you think?
UPDATE:
One important thing is that StartObject(), StopObject() and StatusObject() are constructors and I wanted to assign an object to strategy reference.
You could possibly use a dictionary. Dictionaries store references, which means functions are perfectly viable to use, like so:
operationFuncs = {
Operation.START: strategy_objects.StartObject
Operation.STOP: strategy_objects.StopObject
Operation.STATUS: strategy_objects.StatusObject
(...)
}
It's good to have a default operation just in case, so when you run it use a try except and handle the exception (ie. the equivalent of your else clause)
try:
strategy = operationFuncs[operation]()
except KeyError:
strategy = strategy_objects.DefaultObject()
Alternatively use a dictionary's get method, which allows you to specify a default if the key you provide isn't found.
strategy = operationFuncs.get(operation(), DefaultObject())
Note that you don't include the parentheses when storing them in the dictionary, you just use them when calling your dictionary. Also this requires that Operation.START be hashable, but that should be the case since you described it as a class similar to an ENUM.
Python's equivalent to a switch statement is to use a dictionary. Essentially you can store the keys like you would the cases and the values are what would be called for that particular case. Because functions are objects in Python you can store those as the dictionary values:
operation_dispatcher = {
Operation.START: strategy_objects.StartObject,
Operation.STOP: strategy_objects.StopObject,
}
Which can then be used as follows:
try:
strategy = operation_dispatcher[operation] #fetch the strategy
except KeyError:
strategy = default #this deals with the else-case (if you have one)
strategy() #call if needed
Or more concisely:
strategy = operation_dispatcher.get(operation, default)
strategy() #call if needed
This can potentially scale a lot better than having a mess of if-else statements. Note that if you don't have an else case to deal with you can just use the dictionary directly with operation_dispatcher[operation].
You could try something like this.
For instance:
def chooseStrategy(op):
return {
Operation.START: strategy_objects.StartObject
Operation.STOP: strategy_objects.StopObject
}.get(op, strategy_objects.DefaultValue)
Call it like this
strategy = chooseStrategy(operation)()
This method has the benefit of providing a default value (like a final else statement). Of course, if you only need to use this decision logic in one place in your code, you can always use strategy = dictionary.get(op, default) without the function.
Starting from python 3.10
match i:
case 1:
print("First case")
case 2:
print("Second case")
case _:
print("Didn't match a case")
https://pakstech.com/blog/python-switch-case/
You can use some introspection with getattr:
strategy = getattr(strategy_objects, "%sObject" % operation.capitalize())()
Let's say the operation is "STATUS", it will be capitalized as "Status", then prepended to "Object", giving "StatusObject". The StatusObject method will then be called on the strategy_objects, failing catastrophically if this attribute doesn't exist, or if it's not callable. :) (I.e. add error handling.)
The dictionary solution is probably more flexible though.
If the Operation.START, etc are hashable, you can use dictionary with keys as the condition and the values as the functions to call, example -
d = {Operation.START: strategy_objects.StartObject ,
Operation.STOP: strategy_objects.StopObject,
Operation.STATUS: strategy_objects.StatusObject}
And then you can do this dictionary lookup and call the function , Example -
d[operation]()
Here is a bastardized switch/case done using dictionaries:
For example:
# define the function blocks
def start():
strategy = strategy_objects.StartObject()
def stop():
strategy = strategy_objects.StopObject()
def status():
strategy = strategy_objects.StatusObject()
# map the inputs to the function blocks
options = {"start" : start,
"stop" : stop,
"status" : status,
}
Then the equivalent switch block is invoked:
options["string"]()

Computing a function name from another function name

In python 3.4, I want to be able to do a very simple dispatch table for testing purposes. The idea is to have a dictionary with the key being a string of the name of the function to be tested and the data item being the name of the test function.
For example:
myTestList = (
"myDrawFromTo",
"myDrawLineDir"
)
myTestDict = {
"myDrawFromTo": test_myDrawFromTo,
"myDrawLineDir": test_myDrawLineDir
}
for myTest in myTestList:
result = myTestDict[myTest]()
The idea is that I have a list of function names someplace. In this example, I manually create a dictionary that maps those names to the names of test functions. The test function names are a simple extension of the function name. I'd like to compute the entire dictionary from the list of function names (here it is myTestList).
Alternately, if I can do the same thing without the dictionary, that'd be fine, too. I tried just building a new string from the entries in myTestList and then using local() to set up the call, but didn't have any luck. The dictionary idea came from the Python 3.x documentation.
There are two parts to the problem.
The easy part is just prefixing 'text_' onto each string:
tests = {test: 'test_'+test for test in myTestDict}
The harder part is actually looking up the functions by name. That kind of thing is usually a bad idea, but you've hit on one of the cases (generating tests) where it often makes sense. You can do this by looking them up in your module's global dictionary, like this:
tests = {test: globals()['test_'+test] for test in myTestList}
There are variations on the same idea if the tests live somewhere other than the module's global scope. For example, it might be a good idea to make them all methods of a class, in which case you'd do:
tester = TestClass()
tests = {test: getattr(tester, 'test_'+test) for test in myTestList}
(Although more likely that code would be inside TestClass, so it would be using self rather than tester.)
If you don't actually need the dict, of course, you can change the comprehension to an explicit for statement:
for test in myTestList:
globals()['test_'+test]()
One more thing: Before reinventing the wheel, have you looked at the testing frameworks built into the stdlib, or available on PyPI?
Abarnert's answer seems to be useful but to answer your original question of how to call all test functions for a list of function names:
def test_f():
print("testing f...")
def test_g():
print("testing g...")
myTestList = ['f', 'g']
for funcname in myTestList:
eval('test_' + funcname + '()')

empty function object in python

I've heard that python functions are objects, similar to lists or dictionaries, etc. However, what would be a similar way of performing this type of action with a function?
# Assigning empty list to 'a'
a = list()
# Assigning empty function to 'a'
a = lambda: pass
# ???
How would you do this? Further, is it necessary or proper?
Here is the sense in which I would like to use it for better context:
I have a QListWidget for selecting items which are associated with keys in a dictionary. The values in this dictionary are also dictionaries, which hold certain properties of the items, which I can add. These certain properties are stored as keys, and the values in them are initialized or updated by calling different functions. So, I'm storing a variable in the window which gets updated when a button is pressed to tell this script which property to update.
As you can see, I would like to store the function to map to the data using the correct function based on the situation.
# Get selection from the list
name = selected_item
# Initialize an empty function
f = lambda: pass
# Use property that is being added now, which was updated by the specific button that was pushed
property_list = items[name][self.property_currently_being_added]
if self.property_currently_being_added == "prop1":
f = make_property1()
elif self.property_currently_being_added == "prop2":
f = make_property2()
elif self.property_currently_being_added == "prop3":
f = make_property3()
elif self.property_currently_being_added == "prop4":
f = make_property4()
# map the certain function to the data which was retrieved earlier
added_property = map(f, data)
property_list.append(added_property)
First, the reason this doesn't work:
a = lamdba: pass
… is that lambda only allows an expression, and defines a function that returns the value of the expression. Since pass is a statement, not an expression, this is illegal.
However, this works just fine:
a = lambda: None
In Python, a function that falls off the end without a return statement always returns None. So, these are equivalent:
def a(): return None
def a(): pass
However, I don't see why you want to write this as a lambda and an assignment anyway; the def is shorter, and more readable, and gives you an introspectable function object with a nice name (a instead of <lambda>), and so on. The only reasons to ever use lambda are when you don't want to give the function a name, or when you need to define the function inside an expression. Obviously neither of those are true, because you use the lambda directly inside an assignment statement. So, just use def.
Meanwhile, this is in a sense an "empty function", or at least as empty as possible (as you can see by, e.g., calling dis.dis(a), it still takes two bytecodes to do nothing but fall off the end and return None), but it's not useful for your case. You don't want an "empty function". If you try passing your a to map, you're just going to get a TypeError, because you're trying to call a function of no arguments with one argument. (Because that's what map does.)
What you might want is an identity function, which just returns its argument as-is. Like this:
def a(x): return x
But I'm not sure that's what you want. Did you want to append data as-is in that case? Or did you want to do something different, like return early, or raise an exception, or not append anything, or …?
Finally, I don't see why you want a function at all. Why not just not call map if you have nothing to map? You have a perfectly good else clause that already catches that case (especially handy if what you want to do is return early or raise…). Or, if you prefer, you can start with f = None, and then use an if f: do decide whether to map or not. Or, if you really want:
added_property = [f(element) if f else element for element in data]
… or …
added_property = map(f, data) if f else data
As one last note, instead of a long if/elif chain that repeats the same thing over and over again, you might want a dict:
propfuncs = {'prop1': make_property1(),
'prop2': make_property2(),
'prop3': make_property3(),
'prop4': make_property4()}
Then, all that cruft turns into these two lines:
f = propfuncs.get(self.property_currently_being_added)
added_property = map(f, data) if f else data
Or course an even better design might be to replace all those make_propertyN functions with a single function that you call as make_property(1) or make_property('prop1')… but without seeing what they actually do, I can't be sure of that.
For completeness and since the title is "empty function object in python", more general case is an empty function object that takes any number of parameters, so you can use it in any callback. It's this one:
callback = lambda *_, **__: None
Explanation is here: http://echochamber.me/viewtopic.php?t=64825
I am surprised to learn that you can even do...
def a(): "This is a test"
a()
this feels so much like you're looking for a Nothing functor, I am guessing that if you had knowledge of Monads you wouldn't even need an empty function , as inspiration PyMonad has a nice Nothing implementation, I usually like to create my own, but it's a good starting point.

Scope, using functions in current module

I know this must be a trivial question, but I've tried many different ways, and searched quie a bit for a solution, but how do I create and reference subfunctions in the current module?
For example, I am writing a program to parse through a text file, and for each of the 300 different names in it, I want to assign to a category.
There are 300 of these, and I have a list of these structured to create a dict, so of the form lookup[key]=value (bonus question; any more efficient or sensible way to do this than a massive dict?).
I would like to keep all of this in the same module, but with the functions (dict initialisation, etc) at the
end of the file, so I dont have to scroll down 300 lines to see the code, i.e. as laid out as in the example below.
When I run it as below, I get the error 'initlookups is not defined'. When I structure is so that it is initialisation, then function definition, then function use, no problem.
I'm sure there must be an obvious way to initialise the functions and associated dict without keeping the code inline, but have tried quite a few so far without success. I can put it in an external module and import this, but would prefer not to for simplicity.
What should I be doing in terms of module structure? Is there any better way than using a dict to store this lookup table (It is 300 unique text keys mapping on to approx 10 categories?
Thanks,
Brendan
import ..... (initialisation code,etc )
initLookups() # **Should create the dict - How should this be referenced?**
print getlookup(KEY) # **How should this be referenced?**
def initLookups():
global lookup
lookup={}
lookup["A"]="AA"
lookup["B"]="BB"
(etc etc etc....)
def getlookup(value)
if name in lookup.keys():
getlookup=lookup[name]
else:
getlookup=""
return getlookup
A function needs to be defined before it can be called. If you want to have the code that needs to be executed at the top of the file, just define a main function and call it from the bottom:
import sys
def main(args):
pass
# All your other function definitions here
if __name__ == '__main__':
exit(main(sys.argv[1:]))
This way, whatever you reference in main will have been parsed and is hence known already. The reason for testing __name__ is that in this way the main method will only be run when the script is executed directly, not when it is imported by another file.
Side note: a dict with 300 keys is by no means massive, but you may want to either move the code that fills the dict to a separate module, or (perhaps more fancy) store the key/value pairs in a format like JSON and load it when the program starts.
Here's a more pythonic ways to do this. There aren't a lot of choices, BTW.
A function must be defined before it can be used. Period.
However, you don't have to strictly order all functions for the compiler's benefit. You merely have to put your execution of the functions last.
import # (initialisation code,etc )
def initLookups(): # Definitions must come before actual use
lookup={}
lookup["A"]="AA"
lookup["B"]="BB"
(etc etc etc....)
return lookup
# Any functions initLookups uses, can be define here.
# As long as they're findable in the same module.
if __name__ == "__main__": # Use comes last
lookup= initLookups()
print lookup.get("Key","")
Note that you don't need the getlookup function, it's a built-in feature of a dict, named get.
Also, "initialisation code" is suspicious. An import should not "do" anything. It should define functions and classes, but not actually provide any executable code. In the long run, executable code that is processed by an import can become a maintenance nightmare.
The most notable exception is a module-level Singleton object that gets created by default. Even then, be sure that the mystery object which makes a module work is clearly identified in the documentation.
If your lookup dict is unchanging, the simplest way is to just make it a module scope variable. ie:
lookup = {
'A' : 'AA',
'B' : 'BB',
...
}
If you may need to make changes, and later re-initialise it, you can do this in an initialisation function:
def initLookups():
global lookup
lookup = {
'A' : 'AA',
'B' : 'BB',
...
}
(Alternatively, lookup.update({'A':'AA', ...}) to change the dict in-place, affecting all callers with access to the old binding.)
However, if you've got these lookups in some standard format, it may be simpler simply to load it from a file and create the dictionary from that.
You can arrange your functions as you wish. The only rule about ordering is that the accessed variables must exist at the time the function is called - it's fine if the function has references to variables in the body that don't exist yet, so long as nothing actually tries to use that function. ie:
def foo():
print greeting, "World" # Note that greeting is not yet defined when foo() is created
greeting = "Hello"
foo() # Prints "Hello World"
But:
def foo():
print greeting, "World"
foo() # Gives an error - greeting not yet defined.
greeting = "Hello"
One further thing to note: your getlookup function is very inefficient. Using "if name in lookup.keys()" is actually getting a list of the keys from the dict, and then iterating over this list to find the item. This loses all the performance benefit the dict gives. Instead, "if name in lookup" would avoid this, or even better, use the fact that .get can be given a default to return if the key is not in the dictionary:
def getlookup(name)
return lookup.get(name, "")
I think that keeping the names in a flat text file, and loading them at runtime would be a good alternative. I try to stick to the lowest level of complexity possible with my data, starting with plain text and working up to a RDMS (I lifted this idea from The Pragmatic Programmer).
Dictionaries are very efficient in python. It's essentially what the whole language is built on. 300 items is well within the bounds of sane dict usage.
names.txt:
A = AAA
B = BBB
C = CCC
getname.py:
import sys
FILENAME = "names.txt"
def main(key):
pairs = (line.split("=") for line in open(FILENAME))
names = dict((x.strip(), y.strip()) for x,y in pairs)
return names.get(key, "Not found")
if __name__ == "__main__":
print main(sys.argv[-1])
If you really want to keep it all in one module for some reason, you could just stick a string at the top of the module. I think that a big swath of text is less distracting than a huge mess of dict initialization code (and easier to edit later):
import sys
LINES = """
A = AAA
B = BBB
C = CCC
D = DDD
E = EEE""".strip().splitlines()
PAIRS = (line.split("=") for line in LINES)
NAMES = dict((x.strip(), y.strip()) for x,y in PAIRS)
def main(key):
return NAMES.get(key, "Not found")
if __name__ == "__main__":
print main(sys.argv[-1])

Categories

Resources