Python Adding a List of Class in Another Class - python

I have a class called Question as per below
class Question:
q_count = 0
def __init__(self, s_id, q_id, question):
print("q count is ", Question.q_count)
self._s_id = s_id
self._question_text = question
self._answers = []
self._q_id = Question.q_count
def get_answers(self):
return self._answers
def set_answers(self,answers):
self._answers = answers
def add_answer(self, Answer()):
self._answers.append(Answer())
and I want it to have a list called _answers which is a list of Answer objects. where Answer is another type of class i have created.
class Answer:
def __init__(self, q_id, a_id):
self._q_id = q_id
self._a_id = a_id
# Subclass for multiple choice
class MC_Answer(Answer):
def __init__(self, q_id, a_id, answer_text):
Answer.__init__(self, q_id, a_id)
self._answer_text = answer_text
def get_answer_text(self):
return self._answer_text
def set_answer_text(self, a_id):
self._a_id = a_id;
In another part of my code, I am creating an instance of an MC_Answer object. I also have an instance of a question object. How do I append this onto its answers list??
answer1 = MC_Answer(idQ, 1, answer_text)
new_q.add_answer(answer1)
write_to_file(alist1, "answers.csv")
this is wrong but if i don't have answer1 as a parameter, how does Python know to add that particular instance of an answer?

Your add answer class never uses the parameter, instead you make a new instance of the Answer class and append that to the list, instead you need to modify it to give it a parameter and then use it correctly
def add_answer(self, Answer()):
self._answers.append(Answer())
should be
def add_answer(self, answer):
self._answers.append(answer)

Related

Assinging to a variable

class main_window:
def __init__(self, question):
self.question = question
def question_func(self):
return '{}'.format(self.question)
q1 = main_window('In general, my problem is related to:')
main_window.question_func(q1)
How do i assign main_window.question_func(q1) to a variable which i can call ?
Perhaps you're looking for something like this:
class main_window:
def __init__(self, question):
self.question = question
def question_func(self):
return '{}'.format(self.question)
q1 = main_window('In general, my problem is related to:')
variable = q1.question_func()
print(variable)
Output:
In general, my problem is related to:
I don't get what you're doing "main_window.question_func(q1)". Perhaps you want to create a static/class method??
I think you may be triying to do something like this:
class main_window:
def __init__(self, question):
self.question = question
def question_func(self):
def function_toBe_called():
return '{}'.format(self.question)
# question_func returns a function that
# returns a string, not a string
return function_toBe_called
And then you cand do:
q1 = main_window('In general, my problem is related to:')
variable_youCan_Call = main_window.question_func()
variable_youCan_Call()

Method as an argument with self parameter

Disregard the naming conventions as to what class is part of which it is just a test run.
I need some help with the OOP inheritance i have created a class of Students, Teachers, and the principal. My goal is for the principal to be able to add employees. The problem is i just want to use a for loop to get the names and then pass that method as an attribute for the principal object. i was able to do it with the class Input without the self parameter. can someone tell me
what is going on here and how can i fix this with self. i removed input from names so that my question wont get shut down
class Input:
def count():
cnt = []
for i in range(4):
name = ('Enter name here: ')
cnt.append(name)
return cnt
class Student:
def __init__(self,name,lastname):
self.name = name
self.lastname = lastname
class StudentCouncil(Student):
def __init__(self, name, lastname, tenure):
super().__init__(name,lastname)
self.tenure = tenure
class Principal(StudentCouncil):
def __init__(self, name, lastname, tenure,employees=None):
super().__init__(name,lastname,tenure)
if employees is None:
self.employees = []
else:
self.employees = employees
def display(self):
for names in self.employees:
print(names,end=' ')
count = Input.count()
tij = Principal('Mike','Thoma','3',count)
tij.display()
If the method takes a self parameter, you need to create an instance of the class. So it would be:
class Input:
def count(self):
cnt = []
for i in range(4):
name = input('Enter name here: ')
cnt.append(name)
return cnt
and then you would do:
myinput = Input()
count = myinput.count()
Your count() method doesn't use any attributes of self, so it doesn't currently need to be written this way. But you might want to redefine it like this:
class Input:
def __init__(self, howmany):
self.howmany = howman
def count(self):
return [input('Enter name here: ') for _ in range(self.howmany)]
myinput = Input(4)
count = myinput.count()
If count is all you want from Input, just make it a function:
def input_names():
cnt = []
for i in range(4):
name = ('Enter name here: ')
cnt.append(name)
return cnt
If you want a configurable Input type of some sort, then you want to run count on an instance of that, you need self:
class Input:
def count(self):
cnt = []
for i in range(self.num_names): # if we need some configuration
name = ('Enter name here: ')
cnt.append(name)
return cnt
Else, the kosher way to do this is to use the staticmethod decorator:
class Input:
#staticmethod
def count():
cnt = []
for i in range(4):
name = ('Enter name here: ')
cnt.append(name)
return cnt
Your current code will work as you use it currently, Input.count(), but if you instantiated an input, Input().count() would throw an exception. The staticmethod decorator ensures that this method is safe to call on either the class directly or on an instance of that class.

Adding a new object to a class with user-input(input) in python

I am trying to add new objects to a class(emne) but the new instances of the class needs to be created using user input. So i need a way to be able to chose the name for the object and set some of the values of the objects with user input.
I have already tried to create a function that passes the value of the user input into a x = emner(x) to create it but it only returns:
AttributeError: 'str' object has no attribute 'fagKode'
so i think my issue is that the value of the input is created as a string so that it is not understood as a way to create the function
emne=[]
class Emne:
def __init__(self,fagKode):
self.fagKode = fagKode
self.karakter = ""
emne.append(self)
def leggTilEmne():
nyttEmne = input("test:")
nyttEmne=Emne(nyttEmne)
expected result is that the code creates a new instance of the class.
If by choosing a name you mean your fagKode attribute, what you need is:
fagKode = input('Enter code: ')
Emne(fagKode)
You're adding the instances of Enme to the list in the constructor, so you don't need to save them to a variable.
Alternatively, you can handle that in the function:
emne=[]
class Emne:
def __init__(self,fagKode):
self.fagKode = fagKode
self.karakter = ""
def leggTilEmne():
nyttEmne = input("test:")
enme.append(Emne(nyttEmne))
I'm not sure what exactly you are asking, since you haven't responded to the comments. So,
emne=[]
class Emne:
def __init__(self,fagKode):
self.fagKode = fagKode
self.karakter = ""
emne.append(self)
def leggTilEmne(self, value): # <--- is this what you want
self.nyttEmne= Emne(value)
This is an example of when to use a class method. __init__ should not be appending to a global variable, though. Either 1) have the class method append to a class attribute, or 2) have it return the object and let the caller maintain a global list.
emne = []
class Emne:
emne = []
def __init__(self, fag_kode):
self.fag_kode = fag_kode
self.karakter = ""
#classmethod
def legg_til_emne_1(cls):
nytt_emne = input("test:")
cls.emne.append(cls(nytt_emne))
#classmethod
def legg_til_emne_2(cls):
nyttEmne = input("test:")
return cls(nyttEmne)
Emne.legg_til_emne_1() # Add to Emne.emne
e = Emne.legg_til_emne_2()
emne.append(e)

How to extract string values into object fields

I have this dictionary:
{"id":3,"name":"MySQL","description":"MySQL Database Server - Fedora 21 - medium","image":"","flavor":""}
And I have this object:
class Record():
id = None
name = None
description = None
image = None
flavor = None
How can I assign values from the dictionary to their corresponding class fields?
Take a dict object as the parameter of init function:
class Record(object):
def __init__(self,record_dict):
try:
self.id = record_dict['id']
self.name = record_dict['name']
self.description = record_dict['description']
self.image = record_dict['image']
self.flavor = record_dict['flavor']
except KeyError:
print 'KeyError'
def get_name(self):
return self.name
adict = {"id":3,"name":"MySQL","description":"MySQL Database Server - Fedora 21 - medium","image":"","flavor":""}
one_obj = Record(adict)
print one_obj
print one_obj.get_name()
output:
<__main__.Record object at 0x022E4C90>
MySQL
works for me...
You probably want something like this:
class Record:
def __init__(self, myDict):
self.id = myDict[“id”]
self.name = myDict[“name”]
self.description = myDict[“description”]
self.image = myDict[“image”]
self.flavor = myDict[“flavor”]
And call it:
rec = Record(myDict)
See here to understand the difference between class and instance variables.
Long story short, class variables have a single value for every instance of the class while instance variables values are unique to each instance.
A class variable is defined like this:
class myClass:
Classvar = ‘something’
An instance variable is defined like this:
class myClass:
def __init__():
Self.instanceVar = ‘something else’
This has already been answered here:
Convert Python dict to object?
My favorite method is this one: x.__dict__.update(d)
You can assign them as follows, assuming your dictionary name is input
id = input['id']
name = input['name']
description = input['description']
image = input['image']
flavor = input['flavor']
Try this method in which you grab the attributes of the object:
r = Record()
attributes = [i for i in dir(r) if not i.startswith('_')]
Basically, there are a bunch of background attributes that contain a bunch of underscores. The dir method gets all the attributes and we create a list of the ones that we want. At this point:
# attributes = ['count', 'description', 'flavor', 'id', 'image', 'index', 'name']
So now we use __setattr__ to set the attributes we just grabbed according to the my_dict
for i in attributes:
r.__setattr__(i, my_dict[i])
See the code run online here.
When you create the Record, pass in the dictionary. Then map the key to the value.
Another simple method, see the code here
r = Record()
for k, v in my_dict.items():
exec('r.' + k + '="' + str(v) + '"')

python class adds instances of itself to a list

I have a class for rooms. I want that every time I create an object using that class the object would be added to a list of all rooms.
Rooms class:
class Rooms:
"""Room class, takes type,days, occupied or not and when it frees up"""
def __init__(self, room_type, days, occupied, when_free):
self.room_type = room_type
self.days = days
self.occupied = occupied
self.when_free = arrow.get(when_free,'YYYY-MM-DD')
Any other feedback is appreciated as well!
also not sure if I should create new topic on this but is it possible that when the object is created and True on occupied is passed to the object you wouldn't need to pass 4th variable and it would take it as the current date instead? in short if there is no 4th variable it passes arrow.get(str(arrow.utcnow()),'YYYY-MM-DD') instead
figured out my second issue. I did change the init to:
def __init__(self, room_type, days, occupied, when_free=str(arrow.get(str(arrow.utcnow()),'YYYY-MM-DD'))):
self.room_type = room_type
self.days = days
self.occupied = occupied
self.when_free = arrow.get(when_free,'YYYY-MM-DD')
I would suggest a slightly more elegant and logical way than the above:
class Building(object):
def __init__(self):
self.rooms = []
class Room(object):
def __init__(self, building=None)
if building:
building.rooms.append(self)
self.building = building
b = Building()
r = Room(b)
That way, you don't need every time call b.rooms.append and now it more agreese with OOP.
Ideally, you would want the scope of your room list to be where you plan to use it. Not as part of a room itself. So, if you have a building with rooms:
class Building():
def __init__(self):
self.rooms = []
b = Building()
b.rooms.append(Room(room_type, days, occupied, when_free))
The building is just for an example. The important part is rooms.append(). That should be declared and used wherever you actually need to use the list of rooms.
Might be better just to make the list a class variable:
class Room(object):
rooms = []
def __init__(self, room_type, days, occupied, when_free):
self.room_type = room_type
self.days = days
self.occupied = occupied
self.when_free = arrow.get(when_free,'YYYY-MM-DD')
Room.rooms.append(self)
r = Room('x', 1,2, True)
Room.rooms
[<Room object at 0x00000000C6325550>]
r.rooms
[<Room object at 0x00000000C6325550>]
Since it's a class variable, you can get to it through any class instance, or the class type itself.
edited to go through 'Room' instead of 'self', which is safer...
I was thinking you could decorate the __init__ method with a decorator that appends the instance to a list, to avoid cluttering the __init__ method with the instance registering. Now you only have to add one decorator to each class' init method if you want to keep track of the instances. Something like:
#!/usr/bin/env python3
import sys
class InstanceRegister:
def __call__(self, init):
def register(instance, *args, **kwargs):
init(instance, *args, **kwargs)
try :
instance.__class__.__instances__
except:
instance.__class__.__instances__ = []
instance.__class__.__instances__.append(instance)
return register
class Room:
"""Room class, takes type,days, occupied or not and when it frees up"""
#InstanceRegister()
def __init__(self, room_type, days, occupied, when_free):
self.room_type = room_type
self.days = days
self.occupied = occupied
self.when_free = arrow.get(when_free,'YYYY-MM-DD')
def __str__(self):
return "Room of type {:s}".format(self.room_type)
def main():
r1 = Room('type_a', 1, True, '1999-12-30')
r2 = Room('type_b', 2, True, '2000-12-30')
r3 = Room('type_c', 3, True, '2001-01-30')
for room in Room.__instances__:
print("{:s}".format(room))
return 0
if __name__ == '__main__':
sys.exit(main())
More on decorators at Understanding Python Decorators in 12 Easy Steps!

Categories

Resources