Testing for side-effects in python - python

I want to check that my function has no side-effects, or only side-effects affecting precise variables. Is there a function to check that it actually has no side-effects (or side-effects on only certain variables)?
If not, how can I go about writing my own as follows:
My idea would be something like this, initialising, calling the function under test, and then calling the final method:
class test_side_effects(parents_scope, exclude_variables=[]):
def __init__():
for variable_name, variable_initial in parents_scope.items():
if variable_name not in exclude_variables:
setattr(self, "test_"+variable_name, variable_initial)
def final(self, final_parents_scope):
for variable_name, variable_final in final_parents_scope.items():
if variable_name[:5] is "test_" and variable_name not in exclude_variables:
assert getattr(self, "test_"+variable_name) is variable_final, "Unexpected side effect of %s from %s to %s" % (variable_name, variable_initial, variable_final)
#here parents_scope should be inputted as dict(globals(),**locals())
I'm unsure if this is precisely the dictionary I want...
Finally, should I be doing this? If not, why not?

I'm not familiar with the nested function testing library that you might be writing a test with, but it seems like you should really be using classes here (i.e. TestCase in many frameworks).
If your question then, is relating to getting the parent variables in your TestCase, you could get the __dict__ (It wasn't clear to me what the "Parent" variables you were referring to.
UPDATE: #hayden posted a gist to show the use of parent variables:
def f():
a = 2
b = 1
def g():
#a = 3
b = 2
c = 1
print dict(globals(), **locals()) #prints a=1, but we want a=2 (from f)
g()
a = 1
f()
If this is converted to a dictionary, then the problem is solvable with:
class f(object): # could be unittest TestCase
def setUp(self, a=2, b=1):
self.a = a
self.b = b
def g(self):
#a = 3
b = 2
c = 1
full_scope = globals().copy()
full_scope.update(self.__dict__)
full_scope.update(locals())
full_scope.pop('full_scope')
print full_scope # print a = 1
my_test = f()
my_test.setUp(a=1)
my_test.g()
You are right to look for a tool which has already implemented this. I am hopeful that somebody else will have an already implemented solution.

Related

Copy assignment for class member functions

I have a class A with some member functions that all do the same thing.
class A:
def a():
... boilerplate code ...
b = c = d = a
For debugging reasons, I would like to know the name of each member function at runtime. But since they all point to the same memory address, they will have the same __name__ attribute and I cannot figure out a way to distinguish between A.a and A.b just by looking at the object.
a = A.a
b = A.b
a.__name__ == b.__name__ # this is true
# how do I tell the difference between a and b?
Is there a way to achieve this without manually creating the functions b, c and d with the same boilerplate code?
No. Objects and names in Python live in separate spaces. There's only one function object there, and the function object doesn't know through what name it was conjured.
If you were a masochist, I suppose it would be possible to get a traceback and look at the line of code that called you, but that's just not practical.
You could do something like:
def reala(self,me=None):
pass
def a(self):
return reala('a')
def b(self):
return reala('b')
...

Calling class variable with self

How would you I came up with this interesting (at least to me) example.
import numpy as np
class Something(object):
a = np.random.randint(low=0, high=10)
def do(self):
self.a += 1
print(self.a)
if __name__ == '__main__':
something = Something()
print(something.__str__())
something.do()
something2 = Something()
print(something2.__str__())
something2.do()
something3 = Something()
print(something3.__str__())
something3.do()
The above prints the following in the console:
$ python test.py
<__main__.Something object at 0x7f03a80e0518>
1
<__main__.Something object at 0x7f03a80cfcc0>
1
<__main__.Something object at 0x7f03a80cfcf8>
1
I'm a bit confused because I (wrongly) assumed the value of a would have increased.
I'm able to obtain the behaviour I would expect if I use the #classmethod decorator.
import numpy as np
class Something(object):
a = np.random.randint(low=0, high=10)
#classmethod
def do(cls):
cls.a += 1
print(cls.a)
if __name__ == '__main__':
something = Something()
print(something.__str__())
something.do()
something2 = Something()
print(something2.__str__())
something2.do()
something3 = Something()
print(something3.__str__())
something3.do()
This correctly prints the following in the console.
python test.py
<__main__.Something object at 0x7faac77becc0>
3
<__main__.Something object at 0x7faac77becf8>
4
<__main__.Something object at 0x7faac77c3978>
5
Now, I'm wondering in the first example, when I'm calling self.a, what I'm accessing? It's not a class variable since I don't seem to be able to change its value. It's not an instance variable either, since this seems to be shared among different objects of the same class. How would you call it?
Is this a class variable that I'm using in the wrong way? I know the cls name if a convention, so maybe I'm truly accessing a class variable, but I'm not able to change its value because I haven't decorate the method with the #classmethod decorator.
Is this a sort of illegitimate use of the language? I mean something it's best practice to not do in order to avoid introduce a bug on a later stage?
What is happening is that self.a refers to two things at different times.
When no instance variable exists for a name, Python will lookup the value on the class. So the value retrieved for self.a will be the class variable.
But when setting an attribute via self, Python will always set an instance variable. So now self.a is a new instance variable whose value is equal to the class variable + 1. This attribute shadows the class attribute, which you can no longer access via self but only via the class.
(One minor point, which has nothing to do with the question: you should never access double-underscore methods directly. Instead of calling something2.__str__(), call str(something2) etc.)
Answer by Daniel Roseman clearly explains the problem. Here are some additional points and hope it helps.
You can use type(self).a instead of self.a. Also look at the discussions
Python: self vs type(self) and the proper use of class variables and
Python: self.__class__ vs. type(self)
import numpy as np
class Something(object):
a = np.random.randint(low=0, high=10)
def do(self):
type(self).a += 1
print(type(self).a)
if __name__ == '__main__':
something = Something()
print(str(something ))
something.do()
something2 = Something()
print(str(something2))
something2.do()
something3 = Something()
print(str(something3))
something3.do()

Python use dictionary keys as function names

I would like to be able to use dictionary keys as function names, but I'm not sure if it's possible. As a quick example, instead of class().dothis(dictkey, otherstuff), I'd like to have an option for class().dictkey(otherstuff). Here's a not working code example to give an idea of what I was thinking of.
class testclass:
def __init__(self):
self.dict = {'stuff':'value', 'stuff2':'value2'}
#I know this part won't work, but it gives the general idea of what I'd like to do
for key, value in self.dict.iteritems():
def key():
#do stuff
return value
>>> testclass().stuff()
'value'
Obviously each key would need to be checked that it's not overriding anything important, but other than that, I'd appreciate a bit of help if it's possible to get working.
Basically, my script is to store other scripts in the headers of the Maya scene file, so you may call a command and it'll execute the matching script. It stores the scripts in text format in a dictionary, where I've done a wrapper like thing so you can input args and kwargs without much trouble, and because you can only enter and execute the scripts personally, there's virtually no danger of anything being malicious unless you do it to yourself.
The list is pickled and base64 encoded as it all needs to be in string format for the header, so each time the function is called it decodes the dictionary so you can edit or read it, so ideally I'd need the functions built each time it is called.
A couple of examples from the run function:
Execute a simple line of code
>>> SceneScript().add("MyScript", "print 5")
>>> SceneScript().run("MyScript")
5
Execute a function with a return
>>> SceneScript().add("MyScript", "def test(x): return x*5")
>>> SceneScript().run("MyScript", "test(10)", "test('c')")
[50, 'ccccc']
Pass a variable to a function command
>>> SceneScript().run("MyScript", 'test(a+b)', a=10, b=-50)
[-200]
Execute a function without a return
>>> SceneScript().add("MyScript", "def test(x): print x*5")
>>> SceneScript().run("MyScript", "test(10)", "test('c')")
50
ccccc
[None, None]
Pass a variable
>>> SceneScript().add("MyScript", "print x")
>>> SceneScript().run("MyScript", x=20)
20
So as this question is asking, in terms of the above code, I'd like to have something like SceneScript().MyScript( "test(10)" ), just to make it easier to use.
The only "correct" way I can think of to do this looks like this:
class SomeClass(object):
def __init__(self, *args, **kwargs):
funcs = {'funcname': 'returnvalue', ...}
for func, ret_val in funcs.iteritems():
setattr(self, func, self.make_function(ret_val))
#staticmethod
def make_function(return_value):
def wrapped_function(*args, **kwargs):
# do some stuff
return return_value
return wrapped_function
This should allow you do to:
>>> foo = SomeClass()
>>> foo.funcname()
'returnvalue'
Of course the question of why you'd want to do something like this remains, as yet, unanswered :)
EDIT per updated question:
The problem lies in the fact that you cannot safely assign the method to the function signature. I'm not sure how SceneScript().add works currently, but that's essentially going to have to tie into this somehow or another.
Are you looking for a way to call a function residing inside the current module through a string with its name? If so,
def stuff(arg):
return 5
d = {"stuff":"value","stuff2":"value2"}
print globals()["stuff"](d["stuff"])
will print 5.
I would look into partial functions using functools.partial, in conjunction with __getattribute__:
class Foo:
def __init__(self):
self.a = 5
self.b = 6
def funca(self, x):
print(self.a + x)
def funcb(self, x):
self.a += x
self.funca(x)
mydict = {'funca':1, 'funcb':2}
foo = Foo()
for funcname,param in mydict.items():
print('foo before:', foo.a, foo.b)
print('calling', funcname)
functools.partial(foo.__getattribute__(funcname), param)()
print('foo after:', foo.a, foo.b)
Output:
foo before: 5 6
calling funca
6
foo after: 5 6
foo before: 5 6
calling funcb
9
foo after: 7 6

why does this works SOMETIMES in python ? (variable scope) [duplicate]

This question already has answers here:
Short description of the scoping rules?
(9 answers)
Closed 9 years ago.
This doesn't work: (global name 'a' is not defined)
if True:
a = 3
else:
a = 4
print a
This works:
class A:
def f(self):
if True:
a = 3
else:
a = 4
print a
A().f()
This doesn't work: (global name 'a' is not defined)
class A:
def __init__(self):
a = 3
def f(self):
print a
A().f()
Why is it working in one case and not in another ? I thought that if it works in case (2) then it is because a gets in the class context, but this doesn't make it work in (3)
I saw other discussions but I don't understand everything that is said and cases vary a bit.
EDIT:
example 1 does NOT work, at least in a python 2.7 interpreter. This is why it examples 1 and 2 are contradictory
When you create a variable within a function, like this
def __init__(self):
a = 3
it will be accessible only within that function. That's why both 1 and 2 are working. In the third case, you creating a local variable in one function and trying to access it in another function where the variable is not visible. That's why it fails.
In order to make the third case working, add the variable to the current object (self), like this
def __init__(self):
self.a = 3
And this has to be accessed with the current object only
def f(self):
print self.a
Edit:
Regarding the first statement, if you execute the if..else and the print statements like this, it works fine
>>> if True:
... a = 3
... else:
... a = 4
...
>>> print a
3
In the third example, a is a local variable in __init__ and is discarded when that method ends. Within classes, you need to use self.a to keep it around:
class A:
def __init__(self):
self.a = 3
def f(self):
print self.a
Your other examples actually both work, because in both a is defined locally and printed within the same scope. To copy-paste example 1 from my interpreter (2.7.3):
>>> if True:
a = 3
else:
a = 4
>>> print a
3

python self-less

this works in the desired way:
class d:
def __init__(self,arg):
self.a = arg
def p(self):
print "a= ",self.a
x = d(1)
y = d(2)
x.p()
y.p()
yielding
a= 1
a= 2
i've tried eliminating the "self"s and using a global statement in __init__
class d:
def __init__(self,arg):
global a
a = arg
def p(self):
print "a= ",a
x = d(1)
y = d(2)
x.p()
y.p()
yielding, undesirably:
a= 2
a= 2
is there a way to write it without having to use "self"?
"self" is the way how Python works. So the answer is: No! If you want to cut hair: You don't have to use "self". Any other name will do also. ;-)
Python methods are just functions that are bound to the class or instance of a class. The only difference is that a method (aka bound function) expects the instance object as the first argument. Additionally when you invoke a method from an instance, it automatically passes the instance as the first argument. So by defining self in a method, you're telling it the namespace to work with.
This way when you specify self.a the method knows you're modifying the instance variable a that is part of the instance namespace.
Python scoping works from the inside out, so each function (or method) has its own namespace. If you create a variable a locally from within the method p (these names suck BTW), it is distinct from that of self.a. Example using your code:
class d:
def __init__(self,arg):
self.a = arg
def p(self):
a = self.a - 99
print "my a= ", a
print "instance a= ",self.a
x = d(1)
y = d(2)
x.p()
y.p()
Which yields:
my a= -98
instance a= 1
my a= -97
instance a= 2
Lastly, you don't have to call the first variable self. You could call it whatever you want, although you really shouldn't. It's convention to define and reference self from within methods, so if you care at all about other people reading your code without wanting to kill you, stick to the convention!
Further reading:
Python Classes tutorial
When you remove the self's, you end up having only one variable called a that will be shared not only amongst all your d objects but also in your entire execution environment.
You can't just eliminate the self's for this reason.

Categories