Compiling Python Class Objects into a List - python

I'm trying to learn how to automatically compile all members of a class into a list. This segment of code is not part of a real project, but just an example to help me explain my objective. I can't seem to find any reading material on this, and I don't even know if it is possible or not. Thanks in advance for your answers! =)
class question:
def __init__(self,question,answer,list_of_answers):
self.question=question
self.answer=answer
self.list_of_answers=list_of_answers
question_01=question('''
Which of these fruits is red?
A). Banana
B). Orange
C). Apple
D). Peach
''',"C",("A","B","C","D"))
question_02=question('''
Which of these is both a fruit and a vegetable?
A). Cauliflower
B). Tomato
C). Brocolli
D). Okrah
''',"B",("A","B","C","D"))
'''My objective is to write code that can automatically compile my questions (the
members of my question class) into a list,even if I have hundreds of them, without
having to manually write them into a list.'''
#If there are only two questions, final output should automatically become:
all_questions=[question_01,question_02]
#If there are one hundred questions, final output should automatically become:
all_questions=[question_01,question_02, ... ,question_99,question_100]
#Without having to manually type all of the one hundred questions (or members
#of the question class) to the list.

You shouldn't have 100 question_01 through question_100 variables in the first place. You're going to have a bad time when you want to reorder the questions, or delete one, or add one in the middle. Do you really want to have to rename 98 variables when you want to put a new question between question_02 and question_03?
At this point, you should strongly consider putting your questions into a data file separate from your source code and reading questions from the file. Even if you don't do that, though, you should eliminate the numbered variables. Put the questions in the list to start with. (Also, classes should be named in CamelCase):
questions = [
Question('''
Which of these fruits is red?
A). Banana
B). Orange
C). Apple
D). Peach
''', "C", ("A","B","C","D")),
Question('''
Which of these is both a fruit and a vegetable?
A). Cauliflower
B). Tomato
C). Brocolli
D). Okrah
''', "B", ("A","B","C","D")),
...
]

There is a way of doing what you wanted: obtain a list of all the objects of a given type from a module (or file). I present two solutions:
Option one, from a different module (file):
Say you have the following file:
QuestionModule.py
class question:
def __init__(self,question,answer,list_of_answers):
self.question=question
self.answer=answer
self.list_of_answers=list_of_answers
question_01=question('''
Which of these fruits is red?
A). Banana
B). Orange
C). Apple
D). Peach
''',"C",("A","B","C","D"))
question_02=question('''
Which of these is both a fruit and a vegetable?
A). Cauliflower
B). Tomato
C). Brocolli
D). Okrah
''',"B",("A","B","C","D"))
Then you can get all questions by:
GetQuestions.py
import QuestionModule
def get():
r = []
for attribute in dir(QuestionModule):
#print(attribute," ",type(getattr(QuestionModule,attribute)))
if type(getattr(QuestionModule,attribute)) == QuestionModule.question:
r.append(getattr(QuestionModule,attribute))
return r
l_questions = get()
Or:
import GetQuestions
l_questions = GetQuestions.get()
Option two, from the same module (file):
If you want to do the same from the same file, you can do:
class question:
def __init__(self,question,answer,list_of_answers):
self.question=question
self.answer=answer
self.list_of_answers=list_of_answers
question_01=question('''
Which of these fruits is red?
A). Banana
B). Orange
C). Apple
D). Peach
''',"C",("A","B","C","D"))
question_02=question('''
Which of these is both a fruit and a vegetable?
A). Cauliflower
B). Tomato
C). Brocolli
D). Okrah
''',"B",("A","B","C","D"))
def getQuestions():
import sys
l = dir(sys.modules[__name__])
r = []
for e in l:
if sys.modules[__name__].question==type(getattr(sys.modules[__name__],e)):
r.append(getattr(sys.modules[__name__], e))
return r
L = getQuestions()
for i in L :
print(i)
print(i.question)
You can take out the import sys from the method and put it at the top if you are to call getQuestions multiple times.

Both answers were very good. I wish that I could select both of them as the main answer. I gave it to mm_ because his answer most closely fit my objectives, but I really like user2357112's answer too.
Thanks for the answers everyone!

Related

SWRL rules in OWL 2

I'm currently discovering all the possibilities of the Owlready library.
Right now I'm trying to process some SWRL rules and so far it's been going very good, but I'm stuck at one point.
I've defined some rules in my ontology and now I want to see all the results (so, everything inferred from a rule).
For example, if I had a rule
has_brother(David, ?b) ^ has_child(?b, ?s) -> has_uncle(?s, David)
and David has two brothers, John and Pete, and John's kid is Anna, Pete's kid is Simon, I would like too see something like:
has_brother(David, John) ^ has_child(John, Anna) -> has_uncle(Anna, David)
has_brother(David, Pete) ^ has_child(Pete, Simon) -> has_uncle(Simon, David)
Is this possible in any way?
I thought that maybe if I run the reasoner, I could see it in its output, but I can't find this anywhere.
I appreciate any help possible!
This is my solution:
import owlready2 as owl
onto = owl.get_ontology("http://test.org/onto.owl")
with onto:
class Person(owl.Thing):
pass
class has_brother(owl.ObjectProperty, owl.SymmetricProperty, owl.IrreflexiveProperty):
domain = [Person]
range = [Person]
class has_child(Person >> Person):
pass
class has_uncle(Person >> Person):
pass
rule1 = owl.Imp()
rule1.set_as_rule(
"has_brother(?p, ?b), has_child(?p, ?c) -> has_uncle(?c, ?b)"
)
# This rule gives "irreflexive transitivity",
# i.e. transitivity, as long it does not lead to has_brother(?a, ?a)"
rule2 = owl.Imp()
rule2.set_as_rule(
"has_brother(?a, ?b), has_brother(?b, ?c), differentFrom(?a, ?c) -> has_brother(?a, ?c)"
)
david = Person("David")
john = Person("John")
pete = Person("Pete")
anna = Person("Anna")
simon = Person("Simon")
owl.AllDifferent([david, john, pete, anna, simon])
david.has_brother.extend([john, pete])
john.has_child.append(anna)
pete.has_child.append(simon)
print("Uncles of Anna:", anna.has_uncle) # -> []
print("Uncles of Simon:", simon.has_uncle) # -> []
owl.sync_reasoner(infer_property_values=True)
print("Uncles of Anna:", anna.has_uncle) # -> [onto.Pete, onto.David]
print("Uncles of Simon:", simon.has_uncle) # -> [onto.John, onto.David]
Notes:
One might think has_brother is
symmetric, i.e. has_brother(A, B) ⇒ has_brother(B, A)
transitive, i.e. has_brother(A, B) + has_brother(B, C) ⇒ has_brother(A, C)
irreflexive, i.e. no one is his own brother.
However, transitivity only holds if the unique name assumption holds. Otherwise A could be the same individual as C and this conflicts irreflexivity. Thus I used a rule for this kind of "weak transitivity".
Once, has_brother works as expected the uncle rule also does. Of course, the reasoner must run before.
Update: I published the solution in this Jupyter notebook (which also contains the output of the execution).

Getting a list (and not a list of lists) within a code

I would need to transform a list of lists into a simple list.
Currently I have (wrong output):
Col List1
mouse ([[dog, horse, cat]])
horse ([[mouse, elephant]])
tiger ([[]],[[]])
I would like to have
Col List1
mouse [dog, horse, cat]
horse [mouse, elephant]
tiger []
Code to create the first list above (and that needs to be updated accordingly in order to fix the issue) is
def alexa(x):
surnames, score_lists = [],[]
...
surnames.append(my_surname)
score_lists.append(scores)
return surnames, score_lists
surnames, score_lists = my_function(df)
df['Surname'] = df.Name.apply(lambda x: my_function(x))
df['Score'] = df.Name.apply(lambda x: my_function(x))
(more information in this post: How to avoid code repetition and redundancy)
I have tried as follows:
import itertools
list_surnames=list(itertools.chain(* surnames))
list_scores=list(itertools.chain(* score_lists))
However it seems to be wrong.
If you have any idea on how I can ge the expected output above, it would be great.
You can use numpy.ravel:
import numpy as np
df["List1"] = df["List1"].apply(np.ravel)
# Col List1
#0 mouse [dog, horse, cat]
#1 horse [mouse, elephant]
#2 tiger []

Extract grocery list out of free text

I am looking for a python library / algorithm / paper to extract a list of groceries out of free text.
For example:
"One salad and two beers"
Should be converted to:
{'salad':1, 'beer': 2}
In [1]: from word2number import w2n
In [2]: print w2n.word_to_num("One")
1
In [3]: print w2n.word_to_num("Two")
2
In [4]: print w2n.word_to_num("Thirty five")
35
You can convert to number with using this package and rest of things you can implement as your needs.
Installation of this package.
pip install word2number
Update
You can implement like this.
from word2number import w2n
result = {}
input = "One salad and two beers"
b = input.split()
for i in b:
if type(w2n.word_to_num(i)) is int:
result[b[b.index(i)+1]] = w2n.word_to_num(i)
Result
{'beers': 2, 'salad': 1}
I suggest using WordNet. You can call it from java (JWNL library), etc. Here is the suggestion: for each single word, check it's hypernym. For edibles at the top level of the hypernymy hierarchy you will find " food, nutrient". Which is probably what you want. Now to test this, query the word "beer" in the Online version. Click on the "S", and then click on "inherited hypernym ". You will find this somewhere in the hierarchy:
....
S: (n) beverage, drink, drinkable, potable (any liquid suitable for drinking) "may I take your beverage order?"
S: (n) food, nutrient (any substance that can be metabolized by an animal to give energy and build tissue)
....
You can traverse this hierarchy using the programming language of your choice, etc. Once you flagged all the edibles, then you can catch the number , i.e. 2 in "2 beers", and you have all the information you need. Note that catching the numbers by itself can be a descent coding task! Hope it helps!

Grouping Similar Strings

I'm trying to analyze a bunch of search terms, so many that individually they don't tell much. That said, I'd like to group the terms because I think similar terms should have similar effectiveness. For example,
Term Group
NBA Basketball 1
Basketball NBA 1
Basketball 1
Baseball 2
It's a contrived example, but hopefully it explains what I'm trying to do. So then, what is the best way to do what I've described? I thought the nltk may have something along those lines, but I'm only barely familiar with it.
Thanks
You'll want to cluster these terms, and for the similarity metric I recommend Dice's Coefficient at the character-gram level. For example, partition the strings into two-letter sequences to compare (term1="NB", "BA", "A ", " B", "Ba"...).
nltk appears to provide dice as nltk.metrics.association.BigramAssocMeasures.dice(), but it's simple enough to implement in a way that'll allow tuning. Here's how to compare these strings at the character rather than word level.
import sys, operator
def tokenize(s, glen):
g2 = set()
for i in xrange(len(s)-(glen-1)):
g2.add(s[i:i+glen])
return g2
def dice_grams(g1, g2): return (2.0*len(g1 & g2)) / (len(g1)+len(g2))
def dice(n, s1, s2): return dice_grams(tokenize(s1, n), tokenize(s2, n))
def main():
GRAM_LEN = 4
scores = {}
for i in xrange(1,len(sys.argv)):
for j in xrange(i+1, len(sys.argv)):
s1 = sys.argv[i]
s2 = sys.argv[j]
score = dice(GRAM_LEN, s1, s2)
scores[s1+":"+s2] = score
for item in sorted(scores.iteritems(), key=operator.itemgetter(1)):
print item
When this program is run with your strings, the following similarity scores are produced:
./dice.py "NBA Basketball" "Basketball NBA" "Basketball" "Baseball"
('NBA Basketball:Baseball', 0.125)
('Basketball NBA:Baseball', 0.125)
('Basketball:Baseball', 0.16666666666666666)
('NBA Basketball:Basketball NBA', 0.63636363636363635)
('NBA Basketball:Basketball', 0.77777777777777779)
('Basketball NBA:Basketball', 0.77777777777777779)
At least for this example, the margin between the basketball and baseball terms should be sufficient for clustering them into separate groups. Alternatively you may be able to use the similarity scores more directly in your code with a threshold.

How can I implement a makefile-style algorithm in python

I am implementing an acoustic feature extraction system in python, and I need to implement a makefile-style algorithm to ensure that all blocks in the feature extraction system are run in the correct order, and without repeating any feature extractions stages.
The input to this feature extraction system will be a graph detailing the links between the feature extraction blocks, and I'd like to work out which functions to run when based upon the graph.
An example of such a system might be the following:
,-> [B] -> [D] ----+
input --> [A] ^ v
`-> [C] ----+---> [E] --> output
and the function calls (assuming each block X is a function of the form output = X(inputs) might be something like:
a = A(input)
b = B(a)
c = C(a)
d = D(b,c) # can't call D until both b and c are ready
output = E(d,c) # can't call E until both c and d are ready
I already have the function graph loaded in the form of a dictionary with each dictionary entry of the form (inputs, function) like so:
blocks = {'A' : (('input'), A),
'B' : (('A'), B),
'C' : (('A'), C),
'D' : (('B','C'), D),
'output' : (('D','C'), E)}
I'm just currently drawing a blank on what the makefile algorithm does exactly, and how to go about implementing it. My google-fu appears to be not-very-helpful here too. If someone at least can give me a pointer to a good discussion of the makefile algorithm that would probably be a good start.
Topological sorting
blocks is basically an adjacency list representation of the (acyclic) dependency graph. Hence, to get the correct order to process the blocks, you can perform a topological sort.
As the other helpful answerers have already pointed out, what I'm after is a topological sort, but I think my particular case is a little simpler because the function graph must always start at input and end at output.
So, here is what I ended up doing (I've edited it slightly to remove some context-dependent stuff, so it may not be completely correct):
def extract(func_graph):
def _getsignal(block,signals):
if block in signals:
return signals[block]
else:
inblocks, fn = func_graph[block]
inputs = [_getsignal(i,signals) for i in inblocks]
signals[block] = fn(inputs)
return signals[block]
def extract_func (input):
signals = dict(input=input)
return _getsignal('output',signals)
return extract_func
So now given I can set up the function with
fn = extract(blocks)
And use it as many times as I like:
list_of_outputs = [fn(i) for i in list_of_inputs]
I should probably also put in some checks for loops, but that is a problem for another day.
For code in many languages, including Python try these Rosetta code links: Topological sort, and Topological sort/Extracted top item.

Categories