How to use the methods of the parent class? - python

Here the SMS_Store inherits the Message, but every time I call the parent method there is the error:
NoneType object does not have attribute 'read_message'.
and also the object stored in the list returns a None value??
class Message():
def __init__(self, from_number, time_arrived, text_of_sms):
self.has_been_viewed=False
self.from_number= from_number
self.time_arrived = time_arrived
self.text_of_sms = text_of_sms
def getTime(self):
return self.time_arrived
def getText(self):
return self.text_of_sms
def setView(self):
self.has_been_viewed = True
def check_read(self):
return self.has_been_viewed
class SMS_Store(Message):
def __init__(self):
self.list_=[]
def add_new_arrivals(self,from_number, time_arrived, text_of_sms):
self.list_.append(Message.__init__(self,from_number,time_arrived,text_of_sms))
def message_count(self):
return len(self.list_)
def get_unread_index(self):
unread =[]
for i in range(len(self.list_)):
if(super(SMS_Store,self).check_read() == False):
unread.append(i)
return unread
def read_message(self,index):
self.list_[index].getText()
def delete(self,ints):
a = int(ints)
self.list_.pop(a)
def clear():
for i in list:
self.list_.pop(i)
inbox = SMS_Store()
inbox.add_new_arrivals(12,9,'some nights i stay up')
inbox.add_new_arrivals(12,5,'cashing in my bad luck')
inbox.add_new_arrivals(14,7,'somenights i call it a draw')
inbox.add_new_arrivals(56,0,'somenights i wish that my lips could built a castle.')
inbox.read_message(0)

It's unclear where that error could be coming from since read_message() is only called by the inbox.read_message(0) statement at the end of your code, which wouldn't produce it (although the return value of the read_message() method is always None, since there's no explicit return statement in it).
Regardless, to answer the titular question, to do that explicitly you would use the super() method—but that's not the problem here which is that the SMS_Store class shouldn't be a subclass of Message at all, since it's not a specialization of the Message class...rather it's a container of Message instances.
Below is reworked version of your code that shows how to separate these two classes and get most if not all of the methods working. It also now mostly follows PEP 8 - Style Guide for Python Code recommendations.
class Message:
def __init__(self, from_number, time_arrived, text_of_sms):
self.has_been_viewed = False
self.from_number = from_number
self.time_arrived = time_arrived
self.text_of_sms = text_of_sms
def get_time(self):
return self.time_arrived
def get_text(self):
return self.text_of_sms
def set_viewed(self):
self.has_been_viewed = True
def check_read(self):
return self.has_been_viewed
class SMS_Store:
def __init__(self):
self.list_ = []
def add_new_arrival(self, from_number, time_arrived, text_of_sms):
self.list_.append(Message(from_number, time_arrived, text_of_sms))
def message_count(self):
return len(self.list_)
def get_unread_index(self):
unread = []
for (i, message) in enumerate(self.list_):
if not message.check_read():
unread.append(i)
return unread
def read_message(self, index):
message_text = self.list_[index].get_text()
self.list_[index].set_viewed()
return message_text
def delete(self, index):
self.list_.pop(index)
def clear():
self.list_.clear()
inbox = SMS_Store()
inbox.add_new_arrival(12, 9, 'some nights i stay up')
inbox.add_new_arrival(12, 5, 'cashing in my bad luck')
inbox.add_new_arrival(14, 7, 'somenights i call it a draw')
inbox.add_new_arrival(56, 0, 'somenights i wish that my lips could built a castle.')
print(inbox.get_unread_index()) # -> [0, 1, 2, 3]
print(inbox.read_message(0)) # -> some nights i stay up
print(inbox.get_unread_index()) # -> [1, 2, 3]

You shouldn't use inheritance in this case. Here's corrected version (also fixed code style):
class Message:
def __init__(self, from_number, time_arrived, text_of_sms):
self.has_been_viewed = False
self.from_number = from_number
self.time_arrived = time_arrived
self.text_of_sms = text_of_sms
def get_time(self):
return self.time_arrived
def get_text(self):
return self.text_of_sms
def set_view(self):
self.has_been_viewed = True
def check_read(self):
return self.has_been_viewed
class SMSStore:
def __init__(self):
self._list = []
def add_new_arrivals(self, from_number, time_arrived, text_of_sms):
self._list.append(Message(from_number, time_arrived, text_of_sms))
def message_count(self):
return len(self._list)
def get_unread_index(self):
return list(filter(lambda m: not m.check_read(), self._list))
def read_message(self, index):
return self._list[index].get_text()
def delete(self, index):
a = int(index)
self._list.pop(a)
def clear(self):
self._list = []
inbox = SMSStore()
inbox.add_new_arrivals(12, 9, 'some nights i stay up')
inbox.add_new_arrivals(12, 5, 'cashing in my bad luck')
inbox.add_new_arrivals(14, 7, 'somenights i call it a draw')
inbox.add_new_arrivals(56, 0, 'somenights i wish that my lips could built a castle.')
print(inbox.read_message(0))

Related

Proxy Class in Python 3

I wrote a simple Proxy class in python3, but I have a problem with "was_called" function
class Proxy:
last_invoked = ""
calls = {}
def __init__(self, obj):
self._obj = obj
def __getattr__(self, item):
attrs = dir(self._obj)
if item in attrs:
Proxy.last_invoked = item
if item in Proxy.calls.keys():
Proxy.calls[item] += 1
else:
Proxy.calls[item] = 1
if item in Proxy.calls.keys():
Proxy.calls[item] += 1
else:
Proxy.calls[item] = 1
return getattr(self._obj, item)
else:
raise Exception('No Such Method')
def last_invoked_method(self):
if Proxy.last_invoked == "":
raise Exception('No Method Is Invoked')
else:
return Proxy.last_invoked
def count_of_calls(self, method_name):
if method_name in Proxy.calls.keys():
return Proxy.calls[method_name]
return 0
def was_called(self, method_name):
if method_name in Proxy.calls.keys():
if Proxy.calls[method_name] > 0: return True
return False
class Radio():
def __init__(self):
self._channel = None
self.is_on = False
self.volume = 0
def get_channel(self):
return self._channel
def set_channel(self, value):
self._channel = value
def power(self):
self.is_on = not self.is_on
radio = Radio()
radio_proxy = Proxy(radio)
radio.number = 3
radio_proxy.number = 3
radio_proxy.power()
print(radio_proxy.was_called("number"))
print(radio_proxy.was_called("power"))
"was_called" function is work for functions and attributes that is in radio at first such as "power", but it's not work for new attributes that we add such as "number".
I expect for both print "True", because both of "power" and "number" is called. but first print return False!
What do you suggest?
def Proxy(class_type):
class ProxyClass(class_type):
def __init__(self, *args, **kwargs):
# Set your _calls and _last_invoked here, so that they are not class attributes (and are instead instance attributes).
self._calls = {}
self._last_invoked = ""
# Pass the arguments back to the class_type (in our case Radio) to initialize the class.
super().__init__(*args, **kwargs)
def __getattribute__(self, item):
# We must do this prelimary check before continuing on to the elif statement.
# This is since _calls and _last_invoked is grabbed when self._last_invoked/self._calls is called below.
if item in ("_calls", "_last_invoked"):
return super(ProxyClass, self).__getattribute__(item)
elif not item.startswith("_"):
self._last_invoked = item
self._calls[item] = 1 if item not in self._calls.keys() else self._calls[item] + 1
return super(ProxyClass, self).__getattribute__(item)
def __setattr__(self, item, val):
# Wait until _calls is initialized before trying to set anything.
# Only set items that do not start with _
if not item == "_calls" and not item.startswith("_"):
self._calls[item] = 0
super(ProxyClass, self).__setattr__(item, val)
def last_invoked_method(self):
if self._last_invoked == "":
raise Exception('No Method Is Invoked')
else:
return self._last_invoked
def count_of_calls(self, method_name):
return self._calls[method_name] if method_name in self._calls.keys() else 0
def was_called(self, method_name):
return True if method_name in self._calls.keys() and self._calls[method_name] > 0 else False
return ProxyClass
#Proxy
class Radio():
def __init__(self):
self._channel = None
self.is_on = False
self.volume = 0
def get_channel(self):
return self._channel
def set_channel(self, value):
self._channel = value
def power(self):
self.is_on = not self.is_on
radio = Proxy(Radio)()
radio.number = 3 # Notice that we are only setting the digit here.
radio.power()
print(radio._calls)
print(radio.number) # Notice that this when we are actually calling it.
print(radio._calls)
outputs:
{'is_on': 0, 'volume': 0, 'number': 0, 'power': 1}
3
{'is_on': 0, 'volume': 0, 'number': 1, 'power': 1}
A few modifications here and there, but you should be able to see the bigger idea by reading through the code. From here you should be able to modify the code to your liking. Also note that any variable that starts with _ is automatically removed from the _calls dictionary.
If you rather not use the decorator #Proxy, you may initialize your Radio class (as a proxy) like so:
# Second parentheses is where your Radio args go in.
# Since Radio does not take any args, we leave it empty.
radio_proxy = Proxy(Radio)()
Also, make sure to understand the difference between class attributes, and instance attributes.
Edit:
class Test:
def __init__(self, var):
self.var = var
self.dictionary = {}
def __getattribute__(self, item):
print("we are GETTING the following item:", item)
# If we don't do this, you end up in an infinite loop in which Python is
# trying to get the `dictionary` class to do `self.dictionary['dictionary'] = ...`
if item == "dictionary":
super(Test, self).__getattribute__(item)
else:
self.dictionary[item] = "Now we can use this!"
return super(Test, self).__getattribute__(item)
def __setattr__(self, item, key):
print("we are SETTING the following item:", item)
super(Test, self).__setattr__(item, key)
Notice:
test = Test(4)
outputs:
we are SETTING the following item: var
we are SETTING the following item: dictionary
then following it:
test.var
outputs:
we are GETTING the following item: var
we are GETTING the following item: dictionary

builtins.TypeError: __init__() missing 2 required positional arguments:

My Code:
class SUCHER(EventHandler):
def __init__(self):
self.vokabel = VOKABEL()
EventHandler.__init__(self)
self.button = Button("Suchen!", Point(250,200))
self.button.setFontSize(25)
self.button.setFillColor("lightgrey")
self.button.addHandler(self)
self.lateinischesWort = TextBox(200,50,Point(120,100))
self.übersetzungsText = Rectangle(200,50,Point(380,100))
self.textD = Text("Deutsches Wort", 15, Point(380,50))
self.textL = Text("Lateinisches Wort", 15, Point(120,50))
self.textU = Text(self.vokabel, 25, Point(380,100))
def anzeigenIn(self, Fenster):
Fenster.add(self.button)
Fenster.add(self.übersetzungsText)
Fenster.add(self.lateinischesWort)
Fenster.add(self.textD)
Fenster.add(self.textL)
Fenster.add(self.textU)
def handle(self, Event):
if Event.getDescription() == "mouse click":
self.textL = self.wort
self.textU = self.übersetzung
self.textU.setMessage(self.vokabel)
class BINÄRBAUM:
def __init__(self):
self.wurzel = ABSCHLUSS()
def einfügen(self, Datum):
self.wurzel = self.wurzel.einfügen(Datum)
def inorderAusgeben(self):
self.wurzel.inorderAusgeben()
def preorderAusgeben(self):
self.wurzel.preorderAusgeben()
def postorderAusgeben(self):
self.wurzel.postorderAusgeben()
def suchen(self, Schlüssel):
self.wurzel.suchen(Schlüssel)
class KNOTEN:
def __init__(self, Datum):
self.datum = Datum
self.links = ABSCHLUSS()
self.rechts = ABSCHLUSS()
def einfügen(self, Datum):
if Datum.schlüsselGeben() < self.datum.schlüsselGeben():
self.links = self.links.einfügen(Datum)
else:
self.rechts = self.rechts.einfügen(Datum)
return self
def inorderAusgeben(self):
self.links.inorderAusgeben()
self.datum.informationAusgeben()
self.rechts.inorderAusgeben()
def preorderAusgeben(self):
self.datum.informationAusgeben()
self.links.preorderAusgeben()
self.rechts.preorderAusgeben()
def postorderAusgeben(self):
self.links.postorderAusgeben()
self.rechts.postorderAusgeben()
self.datum.informationAusgeben()
def suchen(self, Schlüssel):
if self.datum.schlüsselGeben() == Schlüssel.casefold():
self.datum.informationAusgeben()
elif self.datum.schlüsselGeben() > Schlüssel.casefold():
self.links.suchen(Schlüssel)
else:
self.rechts.suchen(Schlüssel)
class ABSCHLUSS:
def __init__(self):
pass
def einfügen(self, Datum):
return KNOTEN(Datum)
def inorderAusgeben(self):
pass
def preorderAusgeben(self):
pass
def postorderAusgeben(self):
pass
def suchen(self, Schlüssel):
pass
class VOKABEL:
def __init__(self, Wort, Übersetzung):
self.wort = Wort
self.übersetzung = Übersetzung
def informationAusgeben(self):
print("Das Wort",self.wort,"hat die Bedeutung",self.übersetzung,".")
def schlüsselGeben(self):
return self.wort.casefold()
v = VOKABEL("Nebel", "fog")
s = SUCHER()
b = BINÄRBAUM()
b.einfügen(v)
b.inorderAusgeben()
b.preorderAusgeben()
b.postorderAusgeben()
b.suchen("Nebel")
fenster = Canvas(500,250)
s.anzeigenIn(fenster)
I'm a programmer from Germany and I have a problem.By the way I use the module cs1graphics. I get the Error : builtins.TypeError: init() missing 2 required positional arguments: 'Wort' and 'Übersetzung'
so what can I do to solve this?
class SUCHER(EventHandler):
def __init__(self):
self.vokabel = VOKABEL()
You are instanciating a new VOKABEL class without giving it the 2 arguments it needs. See here the constructor :
class VOKABEL:
def __init__(self, Wort, Übersetzung):

Good way to writing unit test in python

I have simply 'to do' app in python 2.7 and I wrote for this some unit test. This is my first time with python unit test and I just wanna to know idea of unit test.
Someone can tell me whether I'm going in the right direction?
How to improve this tests?
How to check message in IndexError is correct? for this ("IndexError('Note doesn\'t exist')" or IndexError('Returned more then one entry') )
App:
# coding: utf-8
from __future__ import unicode_literals
from shutil import copyfile
import json
import os
DATABASE = 'notes_data/notes.json'
BOARDS = ['to do', 'in progress', 'done']
class NotesManagerMixin(object):
def count(self):
return len(self.notes)
def filter(self, *args, **kwargs):
result = self.notes
for key, value in kwargs.iteritems():
result = [
note for note in result
if getattr(note, key, None) == value or
note.message.startswith(str(value)) or
note.message.endswith(str(value))
]
return NotesQueryset(result)
def get(self, *args, **kwargs):
notes = self.filter(*args,**kwargs)
if notes.count() == 0:
raise IndexError('Note doesn\'t exist')
elif notes.count() == 1:
return notes[0]
else:
raise IndexError('Returned more then one entry')
def first(self):
return self.notes[0]
def last(self):
return self.notes[-1]
class NotesQueryset(NotesManagerMixin):
def __init__(self, notes):
self.notes = [note for note in notes]
def update(self, *args, **kwargs):
for note in self.notes:
for key, value in kwargs.items():
setattr(note, key, value)
note.save()
return self
def delete(self):
for note in self.notes:
note.delete()
return self
def __getitem__(self, idx):
return self.notes[idx]
def __str__(self):
return str(self.notes)
def __repr__(self):
return self.__str__()
class NotesManager(NotesManagerMixin):
def __init__(self):
self.notes = []
def __iter__(self):
return self.next()
def __generate_id(self):
"""
Funkcja pomocnicza do pobrania pewnej wolnej wartości indexu.
"""
try:
return max(note.id for note in self.notes) + 1
except ValueError:
return 1
def all(self):
return NotesQueryset(self.notes)
def add(self, idx, board, message):
self.notes.append(Note(idx=idx, board=board, message=message))
def create(self, board, message):
note = Note(
idx=self.__generate_id(),
board=board,
message=message
)
note.clean()
self.notes.append(note)
note.save()
return note
def next(self):
for note in self.notes:
yield note
def to_dict(self):
return [note.to_dict() for note in self.notes]
class Note(object):
objects = NotesManager()
def __init__(self, idx, board, message):
self.id = idx
self.board = board
self.message = message
def __str__(self):
return 'ID: {}, Board: {}, Message: {}'.format(
self.id,
self.board,
self.message
)
def __repr__(self):
return self.__str__()
def clean(self):
if not self.message:
raise ValueError('Message is required')
if self.board not in BOARDS:
raise ValueError('Board "{}" doesn\'t exists'.format(self.board))
if type(self.id) != int:
raise ValueError('Note id "{}" is invalid'.format(self.id))
def save(self):
for key, note in enumerate(self.objects):
if note.id == self.id:
self.objects.notes[key] = self
break
with open(DATABASE, 'w') as database_file:
json.dump(self.objects.to_dict(), database_file, indent=4)
return True
def delete(self):
for key, note in enumerate(self.objects.notes):
if note.id == self.id:
self.objects.notes.pop(key)
with open(DATABASE, 'w') as database_file:
json.dump(self.objects.to_dict(), database_file, indent=4)
def to_dict(self):
return {
'id': self.id,
'message': self.message,
'board': self.board
}
def load_initial_data():
with open(DATABASE, 'r') as database_file:
json_data = json.load(database_file, encoding='utf-8')
for item in json_data:
Note.objects.add(
idx=item['id'],
board=item['board'],
message=item['message'],
)
load_initial_data()
unit tests:
import unittest
from notes_manager_v2 import NotesQueryset, Note, load_initial_data, NotesManagerMixin
class TestNotesQueryset(unittest.TestCase):
def test_filter(self):
actual = Note.objects.all().filter(board='in progress') # get all notes with board 'in progress'
expected = []
for note in Note.objects.all():
if note.board == 'in progress':
expected.append(note)
self.assertItemsEqual(actual, expected)
def test_get(self):
actual = [Note.objects.all().get(id=1)] # get note with method get
expected = []
for note in Note.objects.all(): # search note with index 1
if note.id == 1:
expected.append(note)
self.assertEqual(actual, expected)
def test_get_fail_1(self):
self.assertRaises(IndexError, lambda:Note.objects.all().get(id=9868976)) # thos note dont exist should raise IndexError
def test_update(self):
from_board = 'to do'
to_board = 'done'
before_change = Note.objects.filter(board=from_board) # use filter method to get all notes with board 'to do'
actual = Note.objects.filter(board=from_board).update(board=to_board) # update all board
self.assertNotEqual(before_change, actual) # check for difference
notes = Note.objects.all()
for note in actual:
self.assertIn(note, notes) # check notes are updated
def test_delete(self):
to_delete = Note.objects.filter(id=2).delete() # find note with filter method and delete it
notes = Note.objects.all()
self.assertNotIn(to_delete, notes)
def test_create(self):
new_note = Note.objects.create(message='lorem ipsum', board='in progress') # create new note
notes = Note.objects.all()
self.assertIn(new_note, notes) #
if __name__ == '__main__':
unittest.main()
Have you looked at the documentation? See doctest. They are an easy way to integrate unit tests into python code. Another option is the unittest framework.

Provide a list of methods in a class for use outside of it

How can I provide a list of methods in a class for use outside of it?
What I'm looking for
When I create an object from a class extending a higher class, I want to get a list of specific methods, some "meta data" of them, and to able to call them outside the class.
Example:
def params(params):
def params_fn(f):
def params_dec(*args, **kwargs):
for i in params:
f.__setattr__(i, params[i])
return f(*args, **kwargs)
return params_dec
return params_fn
class Channel:
queue = None
# some code & docs omitted
def __init__(self, queue):
self.queue = queue
def start(self):
while True:
if not self.check():
break
class channelA(Channel):
extra_methods = ['get_users', 'get_groups']
def start(self):
# omitted
pass
def __internal_method(self, d):
# omitted
pass
#params({"name": "Get users", "desc": "Get a list of users", "icon": "user-plus"})
def get_users(self):
# omitted
return [i for i in self.queue if i.type = 1]
#params({"name": "Get groups", "desc": "Get a list of groups", "icon": "group-plus"})
def get_groups(self):
# omitted
return [i for i in self.queue if i.type = 2]
q = []
ch = channelA(q)
# some code goes here
# it may be something like
# fns = ch.get_extra_fns()
# or anything similar
for fnName in fns:
print("Callable name:", fnName)
print("Name:", fns[fnName].name)
print("Description:", fns[fnName].desc)
print("Icon ID:", fns[fnName].icon)
print("Result:")
print(ch.call(fns[fnName])())
Is it possible to achieve something like this?
You don't need a wrapper for your decorated methods, since you only set attributes of the method-object. To identify your methods, I would suggest to set a special attribute for these methods, iterate over all class methods and pick those, that have this special method set:
def special(**kw):
def mark(function):
function.is_special = True
function.keywords = kw
return function
return mark
class Channel:
def __init__(self, queue):
self.queue = queue
def start(self):
while True:
if not self.check():
break
class ChannelA(Channel):
def start(self):
# omitted
pass
#special(icon="users.png")
def get_users(self):
# omitted
return [i for i in self.queue if i.type == 1]
#special(hint="don't feed the trolls")
def get_groups(self):
# omitted
return [i for i in self.queue if i.type == 2]
ch = ChannelA(q)
for methodname in dir(type(ch)):
method = getattr(ch, methodname)
if getattr(method, 'is_special', False):
print("Callable name:", method.__name__)
print("Keywords:", method.keywords)
print("Result:", method())
def get_extra_fns(self):
fns = {}
for i in self.extra_methods:
fns['i'] = self.__getattribute__(i)
return fns
Python 3:
import types
import inspect
class A:
def a(self):
pass
class B(A):
def b(self, bool_param, int_param):
pass
b = B()
for member_name in dir(B):
member = getattr(B, member_name)
if isinstance(member, types.FunctionType):
member(b, True) # as illustrated by you... this is hardcoded
argspec = inspect.getargspec(member)
args_for_call = {}
for argname in argspec.args:
if argname == 'bool_param':
args_for_call['bool_param'] = True
if argname == 'int_param':
args_for_call['int_param'] = 3
member(b, **args_for_call) # This is less hardcoded

How to use QComboBox selection in function

I have following code using pyqt, which displays two QComboBox's and I want to use the selection values in my applications:
class TACRG(QtGui.QMainWindow, design.Ui_MainWindow):
def __init__(self, parent=None):
super(TACRG, self).__init__(parent)
self.setupUi(self)
self.CList.addItems(["A", "B", "C", "D"])
self.connect(self.CList, QtCore.SIGNAL('activated(QString)'), self.c_chosen)
self.RList.addItems(["Q1", "Q2", "Q3", "Annual"])
self.connect(self.RList, QtCore.SIGNAL('activated(QString)'), self.r_chosen)
def r_chosen(self, text):
report_start, report_end = report_period(text)
def c_chosen(self, text):
accs = get_ucs(text)
def report_period(r_period):
year=date.today().year
if r_period == 'Q1':
return (str(year)+'0101',str(year)+'0331')
elif r_period == 'Q2':
return (str(year)+'0401',str(year)+'0630')
elif r_period == 'Q3':
return (str(year)+'0701',str(year)+'0930')
elif r_period == 'Annual':
return (str(year-1)+'0101',str(year-1)+'1231')
def get_ucs(c_name):
"""DO something""
return """some string"""
Now I wan't to use the values returned from the report_period and get_ucs functions (report_start, report_end, accs) in another funtion, which must be called after these two executed.
How can I achieve this?
Store values in class data members using self, call your other_method in both r_chosen and c_chosen and check for valid values in other_method before use.
class TACRG(QtGui.QMainWindow, design.Ui_MainWindow):
def __init__(self, parent=None):
# Your init code
self.report_start, self.report_end, self.accs = [None] * 3
def r_chosen(self, text):
self.report_start, self.report_end = report_period(text)
self.other_method()
def c_chosen(self, text):
self.accs = get_ucs(text)
self.other_method()
def other_method(self):
#validate if your fields have valid values
if self.report_start and self.report_end and self.accs:
print self.report_start, self.report_end, self.accs
Edit (Other method outside class):
class TACRG(QtGui.QMainWindow, design.Ui_MainWindow):
def __init__(self, parent=None):
# Your init code
self.report_start, self.report_end, self.accs = [None] * 3
def r_chosen(self, text):
self.report_start, self.report_end = report_period(text)
other_method(self.report_start, self.report_end, self.accs)
def c_chosen(self, text):
self.accs = get_ucs(text)
other_method(self.report_start, self.report_end, self.accs)
def other_method(report_start, report_end, accs):
#validate if your fields have valid values
if report_start and report_end and accs:
print report_start, report_end, accs

Categories

Resources