declarations within python class equivalent to _init_? - python

I was wondering if the declarations put at the top of the python class are equivalent to statements in __init__? For example
import sys
class bla():
print 'not init'
def __init__(self):
print 'init'
def whatever(self):
print 'whatever'
def main():
b=bla()
b.whatever()
return 0
if __name__ == '__main__':
sys.exit( main() )
The output is:
not init
init
whatever
As a sidenote, right now I also get:
Fatal Python error: PyImport_GetModuleDict: no module dictionary!
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Any ideas on why this is? Thank you in advance!

No, it's not equivalent. The statement print 'not init' is run while the class bla is being defined, even before you instantiate an object of type bla.
>>> class bla():
... print 'not init'
... def __init__(self):
... print 'init'
not init
>>> b = bla()
init

They aren't exactly the same, because if you do c=bla() afterwards it will only print init
Also, if you reduce your main() to just return 0 it still prints the not init.

Declarations such as that are for the whole class. If print was a variable assignment rather a print statement then the variable would be a class variable. This means that rather than each object of the class having its own, there is only one of the variable for the whole class.

They are not equivalent. Your print statement outside the init method is only called once, when he class is defined. For example, if I were to modify your main() routine to be the following:
def main():
b=bla()
b.whatever()
c = bla()
c.whatever()
return 0
I get the following output:
not init
init
whatever
init
whatever
The not init print statement executes once, when the class is being defined.

Related

Python unittest: Unable to mock imported functions so that conditional evaluates to False

I'm encountering a problem with unit testing in Python. Specifically, when I try to mock a function my code imports, variables assigned to the output of that function get assigned to a MagicMock object instead of the mock-function's return_value. I've been digging through the docs for python's unittest library, but am not having any luck.
The following is the code I want to test:
from production_class import function_A, function_B, function_M
class MyClass:
def do_something(self):
variable = functionB()
if variable:
do_other_stuff()
else:
do_something_else
this is what I've tried:
#mock.patch(path.to.MyClass.functionB)
#mock.patch(<other dependencies in MyClass>)
def test_do_something(self, functionB_mock):
functionB_mock.return_value = None # or False, or 'foo' or whatever.
myClass = MyClass()
myClass.do_something()
self.assertTrue(else_block_was_executed)
The issue I have is that when the test gets to variable = functionB in MyClass, the variable doesn't get set to my return value; it gets set to a MagicMock object (and so the if-statement always evaluates to True). How do I mock an imported function such that when executed, variables actually get set to the return value and not the MagicMock object itself?
We'd have to see what import path you're actually using with path.to.MyClass.functionB. When mocking objects, you don't necessarily use the path directly to where the object is located, but the one that the intepreter sees when recursively importing modules.
For example, if your test imports MyClass from myclass.py, and that file imports functionB from production_class.py, the mock path would be myclass.functionB, instead of production_class.functionB.
Then there's the issue that you need additional mocks of MyClass.do_other_stuff and MyClass.do_something_else in to check whether MyClass called the correct downstream method, based on the return value of functionB.
Here's a working example that tests both possible return values of functionB, and whether they call the correct downstream method:
myclass.py
from production_class import functionA, functionB, functionM
class MyClass:
def do_something(self):
variable = functionB()
if variable:
self.do_other_stuff()
else:
self.do_something_else()
def do_other_stuff(self):
pass
def do_something_else(self):
pass
production_class.py
import random
def functionA():
pass
def functionB():
return random.choice([True, False])
def functionM():
pass
test_myclass.py
import unittest
from unittest.mock import patch
from myclass import MyClass
class MyTest(unittest.TestCase):
#patch('myclass.functionB')
#patch('myclass.MyClass.do_something_else')
def test_do_something_calls_do_something_else(self, do_something_else_mock, functionB_mock):
functionB_mock.return_value = False
instance = MyClass()
instance.do_something()
do_something_else_mock.assert_called()
#patch('myclass.functionB')
#patch('myclass.MyClass.do_other_stuff')
def test_do_something_calls_do_other_stuff(self, do_other_stuff_mock, functionB_mock):
functionB_mock.return_value = True
instance = MyClass()
instance.do_something()
do_other_stuff_mock.assert_called()
if __name__ == '__main__':
unittest.main()
calling python test_myclass.py results in:
..
----------------------------------------------------------------------
Ran 2 tests in 0.002s
OK
What I wound up doing was changing the import statements in MyClass to import the object instead of the individual methods. I was then able to mock the object without any trouble.
More explicitly I changed MyClass to look like this:
import production_class as production_class
class MyClass:
def do_something(self):
variable = production_class.functionB()
if variable:
do_other_stuff()
else:
do_something_else
and changed my test to
#mock.patch(path.to.MyClass.production_class)
def test_do_something(self, prod_class_mock):
prod_class_mock.functionB.return_value = None
myClass = MyClass()
myClass.do_something()
self.assertTrue(else_block_was_executed)

class declaration in exec inits class, but functions don't work

I am going to attach two blocks of code, the first is the main code that is ran the second is the testClass file containing a sample class for testing purposes. To understand what's going on it's probably easiest to run the code on your own. When I call sC.cls.print2() it says that the self parameter is unfulfilled. Normally when working with classes, self (in this case) would be sC.cls and you wouldn't have to pass it as a parameter. Any advice is greatly appreciated on why this is occuring, I think it's something to do with exec's scope but even if I run this function in exec it gives the same error and I can't figure out a way around it. If you'd like any more info please just ask!
import testClass
def main():
inst = testClass.myClass()
classInfo = str(type(inst)).split()[1].split("'")[1].split('.')
print(classInfo)
class StoreClass:
def __init__(self):
pass
exec('from {} import {}'.format(classInfo[0], classInfo[1]))
sC = StoreClass()
exec('sC.cls = {}'.format(classInfo[1]))
print(sC.cls)
sC.cls.print2()
if __name__ == '__main__':
main()
class myClass:
def printSomething(self):
print('hello')
def print2(self):
print('hi')

How to use a variable that inside of a function of a class in another class - Python

I am trying to access to another variable that inside a function and also that is from another class, so I coded it in that way
class Helloworld:
def printHello(self):
self.hello = 'Hello World'
print (self.hello)
class Helloworld2(Helloworld):
def printHello2(self)
print(self.hello)
b = Helloworld2()
b.printHello2()
a = Helloworld()
a.printHello()
However, this gives me that error: AttributeError: 'Helloworld2' object has no attribute 'hello'. So, what would be the simplest way to access to that variable?
That's because you never call printHello(self) that declare your self.hello.
To make it work you need to do:
class Helloworld2(Helloworld):
def printHello2(self):
super().printHello()
print(self.hello)
Or move declaration of you self.hello to __init__() which would be more preferred way.
You should initialise the instance of the class via the __init__() function, this means that when it is created, these values are set.
That would make your code look like:
class Helloworld:
def __init__(self):
#sets self.hello on creation of object
self.hello = 'Hello World'
def printHello(self):
print (self.hello)
class Helloworld2(Helloworld):
def printHello2(self):
print(self.hello)
b = Helloworld2()
b.printHello2()
a = Helloworld()
a.printHello()
An alternative, with your current code is to just call printHello(), either at the top level, with b.printHello(), or within printHello2. Note that in this case, you don't actually need to use super().printHello() as you are not re-defining that function in Helloworld2, though it would be required if you did.

Why is this working in Python nosetests when logically it should not

class TestUM:
#classmethod
def setup_class(will):
""" Setup Class"""
will.var = "TEST"
def setup(this):
""" Setup """
print this.var
def test_number(work):
""" Method """
print work.var
def teardown(orr):
""" Teardown """
print orr.var
#classmethod
def teardown_class(nott):
""" Teardown Class """
print nott.var
Run it as
nosetests -v -s test.py
I am not a Python expert but I cannot figure out why the above code works flawlessly using nose. Every print prints "TEST". What exactly is happening here.
In instance methods, the first argument is the instance itself.
In class methods, the first argument is the class itself.
In your case, rather than name that argument self or cls (the convention), you've named it this, work, orr, and nott. But they're all getting the same argument regardless of the name of the argument.
You've successfully set the attribute var to "TEST", so they all see it correctly.
Example functions without the use of classes:
def test1(attribute):
print attribute
def test2(name):
print name
def test3(cls):
print cls
def test4(self):
print self
Calling those functions:
>>> test1('hello')
hello
>>> test2('hello')
hello
>>> test3('hello')
hello
>>> test4('hello')
hello
The name of the argument doesn't matter. All that matters is what the argument is pointing at, which is always the instance or class

Python - Function isn't 'Global' and so can't be called within Threading Class

So, first off here's my code:
import threading
print "Press Escape to Quit"
class threadOne(threading.Thread): #I don't understand this or the next line
def run(self):
setup()
def setup():
print 'hello world - this is threadOne'
class threadTwo(threading.Thread):
def run(self):
print 'ran'
threadOne().start()
threadTwo().start()
So, the problem is that within my class 'threadOne' the run function runs (as that is called by the threading module) but from there I can not called any other functions. That includes if I make more functions beneath the setup() function. For example above, in my run(self) function I try and call setup() and get 'NameError: global name 'setup' is not defined'.
Does anybody have any ideas or can they explain this to me?
Sam
setup is a method of your Thread instance. Therefore, you call it with self.setup() rather than setup(). The latter is trying to call a global function named setup which does not exist.
Since setup() is an instance method, it must accept self as its first parameter as well.
I assume you meant to do the following:
class threadOne(threading.Thread): #I don't understand this or the next line
def run(self):
self.setup()
def setup(self):
print 'hello world - this is threadOne'

Categories

Resources