Python classes and modules - python

I am teaching myself Python and hit a roadblock with classes and modules.
The code below is something that you would probably never write, but I would like to just understand my error.
import random
class GetRandom:
def __init__(self):
self.data = ""
def ranNumber():
return random.random()
b = GetRandom()
bnum = b.ranNumber
print bnum
The output I am getting is:
<bound method GetRandom.ranNumber of <__main__.GetRandom instance at 0x7fe87818df38>>
I had expected a random number between 0 and 1. What am I doing wrong?
Thanks

There are two problems here:
You forgot to actually invoke GetRandom.ranNumber. Add () after it to do this:
bnum = b.ranNumber()
You need to make GetRandom.ranNumber accept the self argument that is passed implicitly when you invoke the method:
def ranNumber(self):
return random.random()
Once you address these issues, the code works as expected:
>>> import random
>>> class GetRandom:
... def __init__(self):
... self.data = ""
... def ranNumber(self):
... return random.random()
...
>>> b = GetRandom()
>>> bnum = b.ranNumber()
>>> print bnum
0.819458844177
>>>

Related

Function as class attribute

I am writing a class where I would like to pass function as a class attribute and later use it, like that:
class Nevronska_mreza:
def __init__(self, st_vhodni, st_skriti, st_izhod, prenosna_funkcija=pf.sigmoid):
self.mreza = []
self.st_vhodni = st_vhodni
self.st_skriti = st_skriti
self.st_izhodni = st_izhod
self.prenosna_funckija = prenosna_funkcija
self.mreza.append([{'utezi': [random() for i in range(st_vhodni + 1)]} for j in range(st_skriti)])
self.mreza.append([{'utezi': [random() for i in range(st_skriti + 1)]} for j in range(st_izhod)])
def razsirjanje_naprej(self, vhod):
for sloj in self.mreza:
nov_vhod = []
for nevron in sloj:
nevron['izhod'] = self.prenosna_funkcija(self.aktivacijska_funkcija(nevron['utezi'], vhod))
nov_vhod.append(nevron['izhod'])
vhod = nov_vhod
return vhod
but it seems like this isn't the right way, I get the following error:
AttributeError: 'Nevronska_mreza' object has no attribute 'prenosna_funkcija'
Is it possible to do something like that?
Yes you can pass a function around as an argument however you have made a couple of mistakes.
Firstly you have used the word function, although not a reserved word it should be avoided as a name of an entity such as a variable.
Secordly you have used an optional parameter before mandatory parameters which will cause an error such as:
File "test.py", line 5
def __init__(self, function=fun1, data1, data2):
^
SyntaxError: non-default argument follows default argument
Thirdly when calling the method you have not specified the scope, the function name is in the self scope of the object.
Taking all of these into account the following is working code
def fun1(x):
return x+1
class A:
def __init__(self, data1, data2, fn=fun1):
self.fn = fn
self.data1 = data1
self.data2 = data2
def some_method(self):
y = self.fn(self.data1)
print(y)
b = A(1, 2, fun1)
b.some_method()
After posting your full code I can see that you currently have self.prenosna_funckija instead of prenosna_funkcija in the following line:
self.prenosna_funckija = prenosna_funkcija
This would explain the attribute error as when you are calling self.prenosna_funkcija it genuinely does not exist.
You're close:
def fun1(x):
return x+1
class A:
def __init__(self, function=fun1, data1=None, data2=None):
self.function = function
self.data1 = data1
self.data2 = data2
def some_method(self):
y = self.function(self.data1)
return y
a = A(data1 = 41)
result = a.some_method()
print(result)
prints
42

Pythonic way to write attribute which has a random behavior

im writing a code like this
import random
class A:
def __init__(self):
self.att = self.set_att()
def set_att(self):
x = random.randint(0,10)
if x == 1:
return "att1"
elif x == 2:
return "att2"
# ... and so on
my question is: should i do it like this? or there is a better more pythonic way to do it.
i just want to call set_att in the init.
thank you
pycharm says i should use #staticmethod, but i dont understand is de difference
Here are two ideas I can think of:
import random
POSSIBLE_ATT_VALUES = [f'att{x}' for x in range(1, 11)]
class A:
def __init__(self):
# Produce a one-time random value.
self.att = random.choice(POSSIBLE_ATT_VALUES)
class B:
#property
def att(self):
# Every access returns a new random value.
return random.choice(POSSIBLE_ATT_VALUES)
>>> a = A()
>>> a.att
"att3" # Possible value.
>>> a.att
"att3" # The same value.
>>> b = B()
>>> b.att
"att5" # Possible value.
>>> b.att
"att1" # Possibly different value.

Output a dict in python

Hi guys i'm struggling with these classes.
this is what i have to do: cours stands for course and etudiant stands for student. I have to create a class Student that will do the following and i also have to use repr. so create object with student number and add courses
>>> d = Etudiant(12456)
>>> d.addCours('csi2520')
>>> d.addCours('csi2772')
>>> d.addCours('csi2510')
>>> d
12456:[ 'csi2520', 'csi2772', 'csi2510']
>>> d.cours('csi2510')
True
>>> d.cours('csi4900')
False
This is what i did but it's not working
class Etudiant:
cours=[]
def __init__(self, numero):
self.numero=numero
self.classe={self.numero:self.cours}
repr(self.classe)
def addCours(self, cours1):
self.cours.insert(-1,cours1)
please keep it simple i'm a newbie
To alter how a Python object looks when it's printed, you need to implement a magic method called __repr__ (short for representation). You also don't need to store the student number inside the cours variable:
class Etudiant(object):
def __init__(self, numero):
self.numero = numero
self._cours = []
def addCours(self, cours):
self._cours.append(cours)
def cours(self, cours):
return cours in self._cours
def __repr__(self):
return '{}: {}'.format(self.numero, self._cours)
Testing:
>>> d = Etudiant(12456)
>>> d.addCours('csi2520')
>>> d.addCours('csi2772')
>>> d.addCours('csi2510')
>>> d
12456: ['csi2520', 'csi2772', 'csi2510']
>>> d.cours('csi2510')
True
>>> d.cours('csi4900')
False

Python Mock Multiple Calls with Different Results

I want to be able to have multiple calls to a particular attribute function return a different result for each successive call.
In the below example, I would like increment to return 5 on its first call and then 10 on its second call.
Ex:
import mock
class A:
def __init__(self):
self.size = 0
def increment(self, amount):
self.size += amount
return amount
#mock.patch("A.increment")
def test_method(self, mock_increment):
def diff_inc(*args):
def next_inc(*args):
#I don't know what belongs in __some_obj__
some_obj.side_effect = next_inc
return 10
return 5
mock_increment.side_effect = diff_inc
The below page has almost everything that I need except that it assumes that the caller would be an object named "mock", but this can't be assumed.
http://mock.readthedocs.org/en/latest/examples.html#multiple-calls-with-different-effects
You can just pass an iterable to side effect and have it iterate through the list of values for each call you make.
#mock.patch("A.increment")
def test_method(self, mock_increment):
mock_increment.side_effect = [5,10]
self.assertEqual(mock_increment(), 5)
self.assertEqual(mock_increment(), 10)
I tested and this should work
import mock
...
...
#mock.patch.object(ClassB, 'method_2')
#mock.patch.object(ClassA, 'method_1')
def test_same_method_multi_return_value(self, method_1, method_2):
# type: () -> None
method_1.return_value = 'Static value'
method_1.side_effect = [
'Value called by first time'
'Value called by second time'
'...'
]
Version
https://mock.readthedocs.io/en/latest/
mock>=2.0.0,<3.0
I think the popping values off of a list method will be more straightforward.
The below example works for the test you wanted to perform.
Also, I've had a difficult time with the mock library before and have found that the mock.patch.object() method was typically easier to use.
import unittest
import mock
class A:
def __init__(self):
self.size = 0
def increment(self, amount):
self.size += amount
return amount
incr_return_values = [5, 10]
def square_func(*args):
return incr_return_values.pop(0)
class TestMock(unittest.TestCase):
#mock.patch.object(A, 'increment')
def test_mock(self, A):
A.increment.side_effect = square_func
self.assertEqual(A.increment(1), 5)
self.assertEqual(A.increment(-20), 10)
You can use patch and set the absolute path to the module.
from unittest.mock import patch
#patch("src.module2.requests.post")
#patch("src.module1.requests.get")
def test_mock(self, mock_get, mock_post):
data = {}
mock_post.return_value.status_code = 200
mock_post.return_value.json.return_value = data
mock_get.return_value.json.return_value = data
The order used in patches must be kept in method mock parameters, module1 refers to mock_get and module2 refers to mock_post.

Python object that monitors changes in objects

I want a Python object that will monitor whether other objects have changed since the last time they were checked in, probably by storing their hash and comparing. It should behave sort of like this:
>>> library = Library()
>>> library.is_changed(object1)
False
>>> object1.change_somehow()
>>> library.is_changed(object1)
True
>>> library.is_changed(object1)
False
Do you know of anything like that?
Here is an implementation for you. Note that the objects you monitor must be hashable and picklable. Note also the use of a WeakKeyDictionary which means that the Monitor won't stop the monitored objects from being deleted.
from weakref import WeakKeyDictionary
from cPickle import dumps
class Monitor():
def __init__(self):
self.objects = WeakKeyDictionary()
def is_changed(self, obj):
current_pickle = dumps(obj, -1)
changed = False
if obj in self.objects:
changed = current_pickle != self.objects[obj]
self.objects[obj] = current_pickle
return changed
class MyObject():
def __init__(self):
self.i = 1
def change_somehow(self):
self.i += 1
If you test it like this
object1 = MyObject()
monitor = Monitor()
print monitor.is_changed(object1)
object1.change_somehow()
print monitor.is_changed(object1)
print monitor.is_changed(object1)
It prints
False
True
False
It sounds like you're describing the observer pattern. Check here:
http://rudd-o.com/projects/python-observable/
Twisted observable
http://radio.weblogs.com/0124960/2004/06/15.html#a30 - includes explanation
I stole the idea from Nick Craig-Wood, and changed it to a Mix-Class. For me, this is easier to use:
from cPickle import dumps
#base class for monitoring changes
class ChangesMonitor:
_cm_last_dump = None
def is_changed(self):
prev_dump = self._cm_last_dump
self._cm_last_dump = None
cur_dump = dumps(self, -1)
self._cm_last_dump = cur_dump
return (prev_dump is not None) and (prev_dump != cur_dump)
if __name__ == '__main__':
print 'Test Example'
#mix monitoring class with your regular class
class MyGreatObject(ChangesMonitor, object):
one_val = 5
second_val = 7
def some_changes(self):
self.second_val += 5
#and testing
my_obj = MyGreatObject()
print my_obj.is_changed() #False
print my_obj.is_changed() #False
my_obj.some_changes()
print my_obj.is_changed() #True
print my_obj.is_changed() #False
I haven't heard of anything like this... but you could write it pretty easily. Use a dictionary to store a name:hash pair for each object, then use the pickle module to save the dictionary.
This is based on Oduvan's answer, but implemented as a decorator instead of a mix-in class:
from cPickle import dumps
#decorator for monitoring changes
def ChangesMonitor(cls):
def is_changed(self):
prev_dump = self._cm_last_dump
self._cm_last_dump = None
cur_dump = dumps(self, -1)
self._cm_last_dump = cur_dump
return (prev_dump is not None) and (prev_dump != cur_dump)
cls.is_changed = is_changed
cls._cm_last_dump = None
return cls
print 'Test Example'
#decorate your common class
#ChangesMonitor
class MyGreatObject(object):
one_val = 5
second_val = 7
def some_changes(self):
self.second_val += 5
#and testing
my_obj = MyGreatObject()
print my_obj.is_changed() #False
print my_obj.is_changed() #False
my_obj.some_changes()
print my_obj.is_changed() #True
print my_obj.is_changed() #False
Note that #property could be added in front of the def is_changed(self): line such that print my_obj.is_changed() would become print my_obj.is_changed. This might be considered more pythonic...

Categories

Resources