Python - Trouble using inherited method - python

I have an instance of a class, within which I'm trying to use a method defined in the parent.
The code I have produces the following error:
if WordTrigger.isWordIn(story.getTitle()): return True:
TypeError: unbound method isWordIn() must be called with WordTrigger instance as first argument (got str instance instead)
Can anyone steer me in the right direction. i.e. should I be using super() 2.7 version? If so how?
class NewsStory(object):
"""
Data structure for RSS data feed collector
"""
def setUp(self):
pass
def __init__(self, cguid, ctitle, csubject, csummary, clink):
# A globally unique identifier for this news story.
self.cguid = cguid
# The news story's headline.
self.ctitle = ctitle
# A subject tag for this story (e.g. 'Top Stories', or 'Sports').
self.csubject = csubject
# A paragraph or so summarizing the news story.
self.csummary = csummary
# A link to a web-site with the entire story.
self.clink = clink
def getGuid(self):
return self.cguid
def getTitle(self):
return self.ctitle
def getSubject(self):
return self.csubject
def getSummary(self):
return self.csummary
def getLink(self):
return self.clink
#Trigger
class Trigger(object):
def evaluate(self, story):
"""
Returns True if an alert should be generated
for the given news item, or False otherwise.
"""
raise NotImplementedError
#WordTrigger
class WordTrigger(Trigger):
def __init__(self, cword):
# A globally unique identifier for this news story.
self.cword = cword
def isWordIn(self, ctext):
# Checks if word is in text and returns true if present
#Normalize case for word
self.cword = self.cword.lower()
# normalise text case and remove punctuation
self.ctext = self.ctext.lower()
exclude = set(str.punctuation)
self.ctext = ''.join(ch for ch in self.ctext if ch not in exclude)
# Check if word occurs in text
if self.cword in self.ctext:
return True
else:
return False
#TitleTrigger
class TitleTrigger(WordTrigger):
def evaluate(self, story):
"""
Returns True if an alert should be generated
for the given news item, or False otherwise.
"""
if WordTrigger.isWordIn(story.getTitle()): return True
else: return False

In your class TitleTrigger, use self. You access the method through an instance of the class, not on the class object itself.
def evaluate(self, story):
"""
Returns True if an alert should be generated
for the given news item, or False otherwise.
"""
if self.isWordIn(story.getTitle()): return True
else: return False

Related

Why is the DELETE statement using psycopg is not working?

I am working on a delete request. All of my functions are working, but especially this one is not. Actually, it runs, and using my insomnia looks like the row was deleted, but when I get all rows it is still there.
This belongs to my init.py from model folder:
class DatabaseConnector:
#classmethod
def get_conn_cur(cls):
cls.conn = psycopg2.connect(**configs)
cls.cur = cls.conn.cursor()
#classmethod
def commit_and_close(cls):
cls.conn.commit()
cls.cur.close()
cls.conn.close()
This belongs to my anime_model.py folder:
class Anime(DatabaseConnector):
def __init__(self, anime: string, released_date: string, seasons: int) -> None:
self.anime = anime.lower().title()
self.released_date = released_date
self.seasons = seasons
#classmethod
def remove_an_anime(cls, anime_id: int):
cls.get_conn_cur()
cls.create_a_table()
query = f"DELETE FROM animes WHERE id={anime_id} RETURNING *";
cls.cur.execute(query)
anime = cls.cur.fetchall()
cls.cur.close()
cls.conn.close()
return anime
It belongs to my controller folder, anime_controller.py file:
def delete_an_anime(anime_id):
anime_to_delete = Anime.remove_an_anime(anime_id)
if not anime_to_delete:
return {"error": f"id {anime_id} not found"}, HTTPStatus.NOT_FOUND
serialized_anime = dict(zip(anime_columns, anime_to_delete))
return serialized_anime, HTTPStatus.ACCEPTED

How to make a polymorphic dataclass constructor method

I have 3 dataclass objects say:
class Message1:
def __init__(a):
...
class Message2:
def __init__(d,e,f):
...
class Message3:
def __init__(g,i):
...
For these 3 messages I want to make a factory type method which can return one of the three objects if it succeeds and if not it should return either the one it identified as the correct message to be created but failed at creation or it should notify the user that it could not create any of the messages. Are there any OOP patterns for this?
My initial thought was to do a:
def factory_method(**parameters):
try:
Message1(**parameters)
except TypeError:
try:
Message2(**parameters)
except:
try:
Message3(**parameters)
except:
print("Could not deduce message type")
My issue with this idea is that:
It's not a dynamically scalable solution, with each new message class I introduce I need to add a new try catch block
If the whole nested block structure fails, I have no feedback as to why, was the parameters correct for one of the message but wrong value, or was it plain gibberish?
I realize this might be a bit opinion based on what the best outcome is. At the same time it might be the solution is not too elegant and the simplest way is to just tell the factory_method what kind of message to initialize. Any suggestions or ideas would be appreciated.
If you can't join them all in a single class and you can't point a call to a single class, i would match the arguments to the posible class. To make it work a type hint and a "proxy" class is required. This example asumes that any of the classes wont contain a __init__(*args, **kwargs), and to add a new class you just add it to Message.msg_cls, you can eval the global scope if you don't want to add manually each class.
class Message1:
def __init__(self, a: int, alt=None, num=10):
print('Message 1')
class Message2:
def __init__(self, d: str, e: str, f: int):
print('Message 2')
class Message3:
def __init__(self, g: int, i: any):
print('Message 3')
class Message:
msg_cls = (
Message1,
Message2,
Message3
)
#staticmethod
def eq_kwargs(cls, kwargs):
cls_kwargs = cls.__init__.__defaults__
if cls_kwargs is None:
if len(kwargs) > 0:
return False
else:
return True
cls_astr = cls.__init__.__code__
kw_types = [type(t) for t in cls_kwargs]
for k in kwargs:
if k in cls_astr.co_varnames:
if type(kwargs[k]) in kw_types:
kw_types.remove(type(kwargs[k]))
else:
if type(None) in kw_types:
kw_types.remove(type(None))
else:
return False
else:
return False
return True
#staticmethod
def eq_args(cls, args):
cls_args = cls.__init__.__annotations__
if len(cls_args) != len(args):
return False
for a, b in zip(args, cls_args):
if type(a) != cls_args[b] and cls_args[b] != any:
return False
return True
def __new__(cls, *args, **kwargs):
for mc in Message.msg_cls:
if Message.eq_args(mc, args):
if Message.eq_kwargs(mc, kwargs):
return mc(*args, **kwargs)
raise ValueError('Message.__new__, no match')
if __name__ == '__main__':
ms_1_a = Message(1, alt='a')
ms_1_b = Message(2, alt='a', num=5)
ms_2 = Message('X', 'Y', 5)
ms_3_a = Message(1, [1, 4])
ms_3_b = Message(2, Message(10))

How to create a list of instances of a given class

I'm facing problem with my code. In fact, I need to create a list of instances of my class( Patent). The name of the list is patent_ints. But when I'm trying to verify if any element in that list is a Patent one, I'm always getting a False response. And when iterating the first element is like "<__main__.Patent at 0x7f107820b710>".
Here is my code, I need help !
import json
import datetime
patent_data = json.loads(open('NASA_data.json', "r").read())
unique_center = []
for thing in patent_data["Patent_Information"]["Results"]:
for val in thing:
if(val == 'NASA Center'):
unique_center.append(thing[val])
total_num_centers = len(set(unique_center))
class Patent:
def __init__(self, abbreviated_organization_name, dict_data):
self.org_name = abbreviated_organization_name
self.title = dict_data["Title"]
# initialize instance variable called year. The value can be extracted from dict_data.
# This should be a four digit string.
self.year = str(datetime.datetime.strptime(dict_data['Date'], '%m/%d/%Y').year) #dict_data['Date'].split('/')[2]
# initialize an instance variable called month. The value can be extracted from dict_data.
# This should be a two digit string.
self.month = str(datetime.datetime.strptime(dict_data['Date'], '%m/%d/%Y').month) #dict_data['Date'].split('/')[0]
# initialize an instance variable called day. The value can be extracted from dict_data.
# This should be a two digit string.
self.day = str(datetime.datetime.strptime(dict_data['Date'], '%m/%d/%Y').day) #dict_data['Date'].split('/')[1]
self.id = dict_data['Case Number']
self.access_limit = dict_data['SRA Final']
patent_ints = [Patent(i, data) for i in unique_center for data in patent_data["Patent_Information"]["Results"]]
patent_ints[0]
Thank you in advance!
<__main__.Patent at 0x7f107820b710> is the default representation of the class when you try to print it. Add an __str__ or __repr__ method to the class and define some custom logic to return your desired details as a string:
class Patent:
def __init__(self, abbreviated_organization_name, dict_data):
...
def __repr__(self):
# return a dictionary of items in the class but you can return whatever you want
# you could do f'{self.title} {self.id} {self.year}-{self.month}-{self.day}' but str(self.__dict__) is quick to test
return str(self.__dict__)

Use of arguments with property.deleter

I'm trying to define a property deleter with a parameter for an attribute of Character class as follows:
class Character(object):
_status = None
#property
def status(self):
""" Return _status if it exists or False if not."""
return self._status
#status.setter
def status(self, status_value):
"""
Receive the status and the duration(continous or not) and add
it for the _status.
"""
if not self._status:
self._status = []
self._status.append(status_value)
#status.deleter
def status(self, status_value):
"""
Delete the specified object from the _status list.
"""
status = [value for value in self._status
if status_value in value.keys()]
if status:
self._status.remove(self._status.index(status[0]))
I'm trying to delete a specific object from the status.
>>>a = Character()
>>>a.status = 'Test'
Would return a list with 1 element:
>>>a.status
['Test']
If i set the status again, the old value persists and new one is added to the list:
>>>a.status = 'Dazed'
>>>a.status
['Test', 'Dazed']
As well I want to delete only a specific value from the list:
>>>del a.status('Dazed')
And the expected result should be:
>>> a.status
['Test']
The problem is that hen I try:
del a.status('Dazed')
The following error occurs:
SyntaxError: can't delete function call
Is there any way to use arguments with a property.deleter?
This is odd behaviour you are trying to create, and would likely trip up users of your class. I certainly wouldn't expect:
self.status = "happy"
to add the new string to an existing list.
As far as I'm aware there is no way to pass an argument to a #property.deleter.
A better approach might be to make the character.status a set (I am assuming that you meant this to be an instance attribute, but this all stands for class attributes too):
class Character(object):
def __init__(self, ..., status=None):
if status is None:
self.status = set()
else:
self.status = set(status)
...
conan = Character(..., status=("happy", "cold"))
conan.status.add("tired")
conan.status.remove("happy")
One advantage of a set is that it prevents duplicates. Also, it provides for very fast membership tests (e.g. if "warm" in conan.status:) and you can find out if two Character instances have any of the same status easily:
if conan.status.intersection(other_character.status):

Need to print with spaces

I have to print name with spaces, can u help me please?
I got the code like this:
class Perfil:
def __init__(self,email,nome,cidade):
self.email=email
self.nome=nome
self.cidade=cidade
def __str__(self):
return "Perfil de "+self.nome+" ""("+self.email+")"" de "+self.cidade
def getCidade(self):
return self.cidade
def setCidade(self,novo):
self.cidade=novo
def getDominio(self):
t=self.email.rpartition("#")
return t[2]
def limpaNome(self):
new=""
if self.nome.isalpha()==True:
return self.nome
else:
for i in self.nome:
if i.isalpha()==True:
new +=i
return new
When i run the program:
>>> p=Perfil("lol#mail.pt","Ze Car231los", "Porto")
>>> p.limpaNome()
'ZeCarlos'
I need a print like 'Ze Carlos' (with space)
Basically i need to wrote a program using abstract data types (class Profile) to save information for each user. Each object got the following attributes:
email
name
city
The class should have the following methods to manipulate the objects above
Method
__init__(self, email, name, city) - constructor
__str__(self)
getCity(self) - return the value of atribute city
getCity(self.new) - return the atribute city with a new value
getDomain(self) - example: lol#mail.com sugestion: use the method partition (i have to return mail.com only)
cleanName(self) - change the atribute name, deleting characters WICH are not alphabetic or spaces sugestion: use method isalpha
If all you want to do is remove all occurrences of '0','1','2',...,'9' from the string, then you could use str.translate like this:
def limpaNome(self):
return self.nome.translate({ord(c):None for c in '0123456789'})
Note that there is no need for getters/setters like this in Python:
def getCidade(self):
return self.cidade
def setCidade(self,novo):
self.cidade=novo
Instead, just let the user access/set the attribute directly: self.cidade. If, at some point, you'd like to run a function whenever the attribute is accessed or assigned to, then you can make cidade a property without having to change the usage syntax.
You could even make getDominio and limpaNome properties too:
#property
def dominio(self):
t=self.email.rpartition("#")
return t[2]
#property
def limpaNome(self):
return self.nome.translate({ord(c):None for c in '0123456789'})
Notice you don't need paretheses when accessing or setting the property. The syntax looks the same as though lipaNome were a plain attribute:
>>> p=Perfil("lol#mail.pt","Ze Car231los", "Porto")
>>> p.limpaNome
Ze Carllos
>>> p.dominio
mail.pt
import string
# ... the rest of your code
# ...
def limpaNome(self):
whitelist = set(string.ascii_uppercase+string.ascii_lowercase+" ")
if self.nome.isalpha():
return self.nome
else:
return ''.join(ch for ch in self.nome if ch in whitelist)
Or with regex:
import re
# ...
# ...
def limpaNome(self):
return re.sub(r"[^a-zA-Z ]",'',self.nome)
Note that if I were you, I'd do:
class Perfil:
def __init__(self, email, nome, cidade):
self.email = email
self.cidade = cidade
self.nome = limpaNome(nome)

Categories

Resources