I would like to write some code to check student submissions to ensure that a given function includes np.random.choice.
For example:
import numpy as np
def checkme(z, x=[1,2,3], y=4):
tmp = np.random.choice(x, size=y)
if z:
print("z")
return(list(tmp))
I have seen that I can use calls like
tmp = inspect.signature(checkme)
for param in tmp.parameters.values():
print(param.name, ",", param.default)
To determine the parameters and values, which is great, but I want to take this one step further and ensure that the body of the function included a specific function or method. So above, I would want to ensure the students' code included np.random.choice.
How can I access the body of the function to "inspect" and determine if this is True or False?
You can temporarily replace the method you want to check with a wrapper that will let you know if it's called or not through a global variable (or something else of your choosing). I think this is the only real solution, as both checking with string matching and checking the disassembeld code like I suggested in my other answer is error prone and will inevitably miss edge cases.
Here's an example:
class Checker:
def check(self, func, funcargs):
real_np_random_choice = np.random.choice
self.called = False
def wrapper(*args, **kwargs):
self.called = True
return real_np_random_choice(*args, **kwargs)
np.random.choice = wrapper
func(*funcargs)
np.random.choice = real_np_random_choice
return self.called
Checker().check(checkme, (3, [1,2,3], 4)) # -> True
I'm using a class here only because I need to carry the result out of wrapper somehow. This could also be done with a global variable of course.
A more general solution to check that a given method of a given module is called would be:
class Checker:
def __init__(self, module, method):
self.module = module
self.method = method
def check(self, func, funcargs):
real_method = getattr(self.module, self.method)
self.called = False
def wrapper(*args, **kwargs):
self.called = True
return real_method(*args, **kwargs)
setattr(self.module, self.method, wrapper)
func(*funcargs)
setattr(self.module, self.method, real_method)
return self.called
c = Checker(np.random, 'choice')
print(c.check(checkme, (3, [1,2,3], 4)))
You could do something like this:
import inspect
f = 'XXX' # Your student's submission is stored in XXX.py
assert('np.random.choice' in inspect.getsource(__import__(f).checkme))
Instead of inspecting the source code, you could check if the function has been called or not. You can apply a decorator to perform this check:
import numpy as np
# Create your decorator
def iscalled_decorator(func):
def wrapper(*args, **kwargs):
global iscalled
iscalled = True
return func(*args, **kwargs)
return wrapper
# Decorate np.random.choice
np.random.choice = iscalled_decorator(np.random.choice)
# Import your student's function
f = 'XXX'
checkme = __import__(f).checkme
# Set a flag iscalled and call the function
iscalled = False
checkme(3, [1,2,3], 4)
# Check if the flag is True
assert(iscalled)
Assuming you want to do this having the function at hand (even in compiled pyc form) and not through string search operations (which I guess you would have already thought about), then you can use the dis module.
A call of the form y = np.random.choice(x) will be compiled into something like this (output of dis.dis()):
8 0 LOAD_GLOBAL 0 (np)
2 LOAD_ATTR 1 (random)
4 LOAD_METHOD 2 (choice)
6 LOAD_FAST 1 (x)
8 CALL_METHOD 1
10 STORE_FAST 2 (y)
The order of these instructions and their arguments should always be the same assuming that your students are using the global import numpy as np. The third LOAD_METHOD could become LOAD_ATTR depending on how the method is being loaded.
The actual call is more difficult to detect, it could become either CALL_METHOD, CALL_FUNCTION_EX, CALL_FUNCTION_KW or CALL_FUNCTION depending on how it's done. It's also not so straightforward to check that the function being called is actually the one you want like in the above case where it's obvious. Checking that the actual call is made is still possible, but requires keeping track of the Python stack and doing real parsing of the instructions and their arguments, you can check the documentation if you wish to dive into that.
I'll limit myself to just checking if np.random.choice is actually loaded in the checked function. You can do so with the following code:
import dis
def zip3(g):
try:
a, b, c = next(g), next(g), next(g)
while 1:
yield a, b, c
a, b, c = b, c, next(g)
except StopIteration:
pass
def check(func):
for a, b, c in zip3(dis.get_instructions(func)):
if a.opname == 'LOAD_GLOBAL' and a.argval == 'np':
if b.opname == 'LOAD_ATTR' and b.argval == 'random':
if c.opname in ('LOAD_ATTR', 'LOAD_METHOD') and c.argval == 'choice':
return True
return False
check(checkme) # -> True
NOTE: opcodes could change depending on Python version, but I am assuming you will run all the tests under the same Python version, so you can adjust the matches to fit your needs (use dis.dis() to check). Of course with this method you will not be able to catch more convoluted stuff like a = np; b = a.random; b.choice(x) or import numpy as whatever, but that's also true for string matching anyway.
You can use another method of inspect, inspect.getsource that will get the source code of your function as string.
import inspect
import numpy as np
def checkme(z, x=[1,2,3], y=4):
tmp = np.random.choice(x, size=y)
if z:
print("z")
return(list(tmp))
code = inspect.getsource(checkme)
lines = code.split("\n")
for line in lines:
print(line, "np.random.choice" in line)
output:
# def checkme(z, x=[1,2,3], y=4): False
# tmp = np.random.choice(x, size=y) True
# if z: False
# print("z") False
# return(list(tmp)) False
# False
I split the code string to check also on which exact line the method is called
The problem with this approach is for the aliases
if your student as imported numpy in other forms, for example
import numpy as mynp
import numpy
import numpy as npy
or of course for commented code:
# np.random.choice
etc
here some details on the class inspect.
Related
I have a recursive function that I'm looking to test, however I'm having difficulty limiting the recursive call during testing. For example, below is a simple example of a recursive function that calls a bool_function(n) to check if it should break the recursive loop.
def factorial(n):
if bool_function(n):
return 1
else:
return n * factorial(n-1)
What would be the best way to test or mock bool_function(n) so that it is true for the first iteration and false for any call after?
You could always implement a class to encapsulate the state and give you more flexibility, here's a sketch:
>>> class MockBoolCheck:
... def __init__(self, fail_after=0):
... self.count = 0
... self.fail_after = fail_after
... def __call__(self, n):
... called = self.count
... self.count += 1
... return called <= self.fail_after
...
>>> bool_function = MockBoolCheck()
>>> bool_function(42)
True
>>> bool_function(42)
False
>>> bool_function(42)
False
>>> bool_function(42)
False
>>> bool_function(42)
False
If, beside other suggested solutions, you really want to mock it, and want to do it yourself (without the mocking libraries) by just replacing the mocked function.
# Your code (or module):
def bool_function(n):
print('REAL bool-function {}'.format(n))
return n <= 0
def factorial(n):
print('FACT {}'.format(n))
if bool_function(n):
return 1
else:
return n * factorial(n-1)
# Mocking code (or module):
def mock_function(n):
print('MOCK bool-function {}'.format(n))
global bool_function
bool_function = bool_func_orig # restore on the first use
return False
bool_func_orig = bool_function
bool_function = mock_function # mock it
# Go run it!
factorial(10)
If these are two separate modules, then instead of global bool_function & bool_function=... just use the somemodule.bool_function=....
If you want to use the mocking library, then it depends on which library you use. If that is unittest.mock, then you should play with side_effect=... & wraps=... (see the manual). The same approach: mock it, and un-mock it from inside the side effect on the first use.
I generally try not to leave debug code around unless I expect to use it regularly, but you could just include a default argument for the sake of debugging to force the execution to follow a particular path.
def factorial(n, debug=False):
if bool_function(n) or debug:
return 1
else:
return n * factorial(n-1)
This naturally implies that you're also externally testing bool_function()
Just pass the function as an argument. If function is None you can apply some default behavior if that is desired.
This is a common approach used in queries to iterables (e.g. Django queries or Peewee queries) in most of languages.
A function that returns boolean is usually called a predicate
def factorial(n, predicate=None):
if not predicate:
predicate = lambda x: x > 2
if predicate(n):
return 1
else:
return n * factorial(n-1)
For python > 3.6
import mock
class RecursividadeTest(unittest.TestCase):
def test_recursive(self):
with mock.patch('path.factorial') as mock_fact:
factorial(3)
self.assertTrue(mock_fact.called)
self.assertGreaterEqual(mock_fact.call_count, 2)
def test_recursive_2(self):
with mock.patch('incolumepy.sequences.fibonacci.fibonacci') as mock_fib:
for i in range(1, 5, -1):
expected = i - 1
fibonacci(i)
self.assertTrue(mock_fib.called)
self.assertEqual(mock_fib.call_count, expected)
I've been tasked with something a bit unusual and unexpectedly puzzling - Display the source code of a particular class's implementation of a method.
In [1]: class Demonstration:
...: def cost():
...: return 42
...:
In [2]: class OtherDemo:
...: def cost():
...: return 43
...:
In this example, I'd want to find the text def cost(): and the following lines at the appropriate indent for either given class.
modules like inspect or dis are nearly what I'm looking for, but I want to display the python code, such as is displayed during a traceback; not bytecode.
I'm also not opposed to parsing the source files, either - is there a library that text editors might use for autocompletion or indent calculations that could find a specific method in a class?
It sounds like the inspect library is exactly what you need, in particular, the function getsourcelines:
In [1]: def foo(x):
...: x += 3
...: x += 4
...: return x
...:
In [2]: import inspect
In [3]: inspect.getsourcelines(foo)
Out[3]: (['def foo(x):\n', ' x += 3\n', ' x += 4\n', ' return x\n'], 1)
In [4]: source_code = _
In [6]: print(''.join(source_code[0]))
def foo(x):
x += 3
x += 4
return x
From the docs:
Return a list of source lines and starting line number for an object. The argument may be a module, class, method, function, traceback, frame, or code object. The source code is returned as a list of the lines corresponding to the object and the line number indicates where in the original source file the first line of code was found. An IOError is raised if the source code cannot be retrieved.
In Python, because of the ability to dynamically modify anything it can be very tricky to map back to a source definition. The definition, after all, could be created on the fly.
Here's a somewhat simplistic example. Dynamic definitions can be much trickier even than this, and it's especially tricky if implementation occurs in a pre-compiled module.
def make_random_function(coin='Heads'):
if coin == 'Heads':
def foo(self, a):
print a
elif coin == 'Tails':
def foo(self, a, b):
return a + b
else:
def foo(self, *args, **kwargs):
raise ValueError('Invalid coin used to create function.')
foo.__name__ = "dynamic_foo"
foo.__doc__ = "Good luck buddy."
return foo
import random
val = random.random()
if val > 0.51:
coin = 'Heads'
elif val < 0.49:
coin = 'Tails'
else:
coin = 'Trick'
function = make_random_function(coin)
MyType = type("MyType", (object,), {function.__name__:function})
m = MyType()
When I run this and then call m.dynamic_foo() I see this:
In [313]: coin
Out[313]: 'Trick'
In [314]: val
Out[314]: 0.5099718112195031
In [315]: m.dynamic_foo()
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-315-70b3caeb205b> in <module>()
----> 1 m.dynamic_foo()
<ipython-input-310-475ea0810d8d> in foo(*args, **kwargs)
8 else:
9 def foo(*args, **kwargs):
---> 10 raise ValueError('Invalid coin used to create function.')
11
12 foo.__name__ = "dynamic_foo"
ValueError: Invalid coin used to create function.
In [316]: m
Out[316]: <__main__.MyType at 0x7f37e70b3ad0>
Even if I use inspect.getsourcelines(m.dynamic_foo) it's a bit misleading:
In [319]: inspect.getsourcelines(m.dynamic_foo)
Out[319]:
([u' def foo(self, *args, **kwargs):\n',
u" raise ValueError('Invalid coin used to create function.')\n"],
9)
Notice how the function's source shows that its name is "foo" (not "dynamic_foo") and it's not a class method or instance method of MyType or anything. This is technically correct in the sense that it is the actual lines of source code, but it's not necessarily what someone might expect to see, since it's a definition that exists in a manner disconnected from how it gets dynamically injected into a class definition.
And this is a simple example of this kind of dynamic function creation and dynamic class manipulation. The more complicated this gets, the less reliable it is to count on inspecting source lines as a reasonable way to understand the function's implementation.
I am trying to create a set of functions in python that will all do a similar operation on a set of inputs. All of the functions have one input parameter fixed and half of them also need a second parameter. For the sake of simplicity, below is a toy example with only two functions.
Now, I want, in my script, to run the appropriate function, depending on what the user input as a number. Here, the user is the random function (so the minimum example works). What I want to do is something like this:
def function_1(*args):
return args[0]
def function_2(*args):
return args[0] * args[1]
x = 10
y = 20
i = random.randint(1,2)
f = function_1 if i==1 else function_2
return_value = f(x,y)
And it works, but it seems messy to me. I would rather have function_1 defined as
def function_1(x):
return x
Another way would be to define
def function_1(x,y):
return x
But that leaves me with a dangling y parameter.
but that will not work as easily. Is my way the "proper" way of solving my problem or does there exist a better way?
There are couple of approaches here, all of them adding more boiler-plate code.
There is also this PEP which may be interesting to you.
But 'pythonic' way of doing it is not as elegant as usual function overloading due to the fact that functions are just class attributes.
So you can either go with function like that:
def foo(*args):
and then count how many args you've got which will be very broad but very flexible as well.
another approach is the default arguments:
def foo(first, second=None, third=None)
less flexible but easier to predict, and then lastly you can also use:
def foo(anything)
and detect the type of anything in your function acting accordingly.
Your monkey-patching example can work too, but it becomes more complex if you use it with class methods, and does make introspection tricky.
EDIT: Also, for your case you may want to keep the functions separate and write single 'dispatcher' function that will call appropriate function for you depending on the arguments, which is probably best solution considering above.
EDIT2: base on your comments I believe that following approach may work for you
def weigh_dispatcher(*args, **kwargs):
#decide which function to call base on args
if 'somethingspecial' in kwargs:
return weight2(*args, **kwargs)
def weight_prep(arg):
#common part here
def weight1(arg1, arg2):
weitht_prep(arg1)
#rest of the func
def weight2(arg1, arg2, arg3):
weitht_prep(arg1)
#rest of the func
alternatively you can move the common part into the dispatcher
You may also have a function with optional second argument:
def function_1(x, y = None):
if y != None:
return x + y
else:
return x
Here's the sample run:
>>> function_1(3)
3
>>> function_1(3, 4)
7
Or even optional multiple arguments! Check this out:
def function_2(x, *args):
return x + sum(args)
And the sample run:
>>> function_2(3)
3
>>> function_2(3, 4)
7
>>> function_2(3, 4, 5, 6, 7)
25
You may here refer to args as to list:
def function_3(x, *args):
if len(args) < 1:
return x
else:
return x + sum(args)
And the sample run:
>>> function_3(1,2,3,4,5)
15
Imagine I've got a Python module with some function in it:
def sumvars(x, y, z):
s = x
s += y
s += z
return s
But sometimes I want to get results of some intermediate calculations (for example, I could have a function which reverses a matrix and would like to know the determinant which has been calculated as an intermediate step as well). Obviously, I wouldn't want to redo those calculations again if they were already done within that function.
My first idea is to return a dict:
def sumvars(x, y, z):
d = {}
s = x
d['first_step'] = s
s += y
d['second_step'] = s
s += z
d['final'] = s
return d
But I don't recall any functions in numpy or scipy which return dicts and so it seems like this might be not a good idea. (Why?) Also routinely I'll always have to type sumvars(x,y,z)['final'] for a default return value...
Another option I see is creating global variables but seems wrong having a bunch of them in my module, I would need to remember their names and in addition not being attached to the function itself looks like a bad design choice.
What would be the proper function design for such situation?
Generally when you have two different ways you want to return data, go ahead and make two different functions. "Flat is better than nested", after all. Just have one call the other so that you Don't Repeat Yourself.
For example, in the standard library, urllib.parse has parse_qs (which returns a dict) and parse_qsl (which returns a list). parse_qs just then calls the other:
def parse_qs(...):
parsed_result = {}
pairs = parse_qsl(qs, keep_blank_values, strict_parsing,
encoding=encoding, errors=errors)
for name, value in pairs:
if name in parsed_result:
parsed_result[name].append(value)
else:
parsed_result[name] = [value]
return parsed_result
Pretty straightforward. So in your example it seems fine to have
def sumvars(x, y, z):
return sumvars_with_intermediates(x, y, z).final
def sumvars_with_intermediates(x, y, z):
...
return my_namedtuple(final, first_step, second_step)
(I favor returning namedtuples instead of dicts from my APIs, it's just prettier)
Another obvious example is in re: re.findall is its own function, not some configuration flag to search.
Now, the standard library is a sprawling thing made by many authors, so you'll find counterexamples to every example. You'll far more often see the above pattern rather than one omnibus function that accepts some configuration flags, though, and I find it far more readable.
Put the common calculation into its own function as Jayanth Koushik recommended if that calculation can be named appropriately. If you want to return many values (an intermediate result and a final result) from a single function then a dict may be an overkill depending on what is your goal but in python it is much more natural to simply return a tuple if your function has many values to return:
def myfunc():
intermediate = 5
result = 6
return intermediate, result
# using the function:
intermediate, result = myfunc()
Not sure if function attributes is a good idea:
In [569]: def sumvars(x, y, z):
...: s = x
...: sumvars.first_step = s
...: s += y
...: sumvars.second_step = s
...: s += z
...: return s
In [570]: res=sumvars(1,2,3)
...: print res, sumvars.first_step, sumvars.second_step
...:
6 1 3
Note: as #BrenBarn mentioned, this idea is just like global variables, your previously calculated "intermediate results" could not be stored when you want to reuse them.
Just came up with this idea which could be a better solution:
def sumvars(x, y, z, mode = 'default'):
d = {}
s = x
d['first_step'] = s
s += y
d['second_step'] = s
s += z
d['final'] = s
if mode == 'default':
return s
else:
return d
I belive the proper solution is to use a class, to have a better grasp of what you are modeling. For example in the case of the Matrix, you could simply store the determinant in the "determinant" attribute.
Here is an example using your matrix example.
class Matrix:
determinant = 0
def calculate_determinant(self):
#calculations
return determinant
def some_method(self, args):
# some calculations here
self.determinant = self.calculate_determinant()
# other calculations
matrix = Matrix()
matrix.some_method(x, y, z)
print matrix.determinant
This also allows you to separate your method into simpler methods, like one for calculating the determinant of your matrix.
Another variation:
def sumvars(x, y, z, d=None):
s = x
if not d is None:
d['first_step'] = s
s += y
if not d is None:
d['second_step'] = s
s += z
return s
The function always returns the desired value without packing it into a tuple or dictionary. The intermediate results are still available, but only if requested. The call
sumvars(1, 2, 3)
just returns 6 without storing intermediate values. But the call
d = {}
sumvars(1, 2, 3, d)
returns the same answer 6 and inserts the intermediate calculations into the supplied dictionary.
Option 1. Make two separate functions.
Option 2. Use a generator:
>>> def my_func():
... yield 1
... yield 2
...
>>> result_gen = my_func()
>>> result_gen
<generator object my_func at 0x7f62a8449370>
>>> next(result_gen)
1
>>> next(result_gen)
2
>>> next(result_gen)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
Inspired by #zhangxaochen solution, here's my take on your problem using class attributes:
class MyClass():
def __init__(self):
self.i = 4
def f(self):
s = self.i
MyClass.first_step = s
print(MyClass.first_step)
s += self.i
MyClass.second_step = s
print(MyClass.second_step)
s += self.i
return s
def main():
x = MyClass()
print(x.f()) # print final s
print(x.first_step)
print(x.second_step)
print(MyClass.second_step)
Note: I included several prints to make it more explicit how attribute values can be retrieved.
Result:
4
8
12
4
8
8
I am attempting to write a program to perform arithmetic mod n, given n. I was wondering if there is any way within Python (preferably 2.7) to dynamically define a function such that its behavior depends on the name used to call it. More concretely, I would like to define a function named "*mod", where * is an integer, that then does arithmetic mod *. Perhaps more clearly, I would like to write one function definition for *mod that defines the functions 2mod, 3mod, 4mod, and so on. Is this possible? I apologize if a similar question has already been asked or if my answer is readily available in documentation; I tried to search for it, but I didn't know exactly how to describe the functionality that I'm looking for, so I may have missed it.
Thanks!
You don't want to do that. Just make a simple function and pass both numbers as arguments:
def mod(x, n):
return x % n
print mod(5, 2)
# 1
Well, if you really, really want to, look at this quick hack. It uses a wrapper class to wrap the module in a class, so you can use __getattr__:
import sys
import functools
def add(a, b):
return a + b
def sub(a, b):
return a - b
class Wrapper(object):
def __init__(self, wrapped):
self.wrapped = wrapped
def __getattr__(self, name):
try:
# quick hack. Don't try this at home :-)
f = ''.join(x for x in name if not x.isdigit())
n = ''.join(x for x in name if x.isdigit())
return functools.partial(getattr(self.wrapped, f), int(n))
except:
return getattr(self.wrapped, name)
sys.modules[__name__] = Wrapper(sys.modules[__name__])
Now, when you call e.g. add10(12) on this module, the result is 22. Note that method names must not start with a number, but you could use names like _add and call the methods like _55add(45) and so on.
But I would follow Haidro advice: You don't want to do that. Just calling the method with two arguments is a lot simpler.
Using globals, lambda:
for i in range(2, 5):
globals()['mod{}'.format(i)] = lambda x, n=i: x % n
assert mod2(4) == 0
assert mod2(3) == 1
assert mod3(2) == 2
assert mod3(1) == 1
assert mod4(1) == 1
assert mod4(2) == 2
assert mod4(3) == 3
assert mod4(9) == 1
You could achieve this by generating the functions as a string, and then exec this string to get the function in the current namespace. Something like:
n = 2
s = 'def mod%i(x):' % n
s += ' return x %% %i' % n
exec s
This would define the function mod2(x)