How to properly implement a list as a instance variable? - python

So I'm reading through An Introduction to Programming Using Python and doing the exercises for my own edification. I'm learning about custom classes and get to a part where it states: "The program should use a class named Quizzes that has an instance variable to hold a list of the six grades..." So I tried the following:
class Quizzes:
def __init__(self, grade1=0):
self._grade1 = grade1
def setGrade1(self, grade1):
self._grade1 = grade1
def getGrade1(self):
return self._grade1
def grades(self):
return []
def gradeInsert(self, a=grades()):
a.append(self._grade1)
In this case, I get "TypeError: grades() missing 1 required positional argument: 'self'.
I've also tried:
def __init__(self, grade1=0, grades=[]):
self._grade1 = grade1
self._grades = grades
def setGrade1(self):
self._grade1 = grade1
def setGrades(self):
self._grades = [self.getGrade1()]
def getGrades(self):
return self._grades
But I get a blank [ ]. Any modification I do to grades=[ ] in _ init _ reflects in my getGrades call. So how do I get setGrades to actually set? Or am I totally off the mark?

Instance variables should be initialized inside of __init__
class Quizzes:
def __init__(self):
self._grades = [] # Here, we initialize the list
def grades(self):
return self._grades # We can return the instance variable here
def gradeInsert(self, a): # No reason for a default argument here
self._grades.append(a) # Add the value to the list

In your first example you try to call grades() which is a member function of the Quizzes class. Member functions expect the instance as the first argument, either before the dot (the_instance.grades()) or as (less common) as an explicit argument (grades(the_instance)). You provide neither and thus Python complains.
In your second example it is not clear what you actually do after the class is defined.
In general, the two classes do not have much to do with the exercise, which would be solved by the following:
class quizzes(object):
def __init__(self, grades = None):
if grades is None:
self.grades = [0]*6
else:
self.grades = grades[:6]
BTW: it is not recommended to use a mutable object as default argument as this object is shared between all invocations.

Related

assign None values to all arguments of an arbitrary class'

I want to make a method whose arguments are an arbitrary class and a list of instances.
let's say the name of the class is 'Price' and the name of the list is 'price_list'
def CreateHTML(_class, _list):
one_instance = _class
list_members = list(one_instance.__dict__) ##to get the list of member variables' names
n= len(list_members)
CreateHTML(Price(), price_list)
but the problem is that it works well only if I initially set 'None' values to all arguments of 'Price' class.
class Price:
def __init__(self, name= None, data = None):
self.name = name
self.data = data
is there any ways that the assignment of 'None' values can be automatically handled inside the CreateHTML method??? so that i don't need to initially set Nones to the class. (like below)
class Price:
def __init__(self, name, data):
self.name = name
self.data = data
Thanks!!!
CreateHTML(Price(), price_list) : here Price is expecting 2 items 'name' and 'data'. You have to either pass it while calling the Price('name', 'data') or you have to pass None in your init
As also noted in my comment above, Price() isn't a class, it is an instance of the class Price. By calling Price() you are essentially instantiating Price with all variables as None. This will only work if Price has default argments such as is set with def __init__(self, name= None, data = None).
If you want a general method with which to instantiate arbitrary classes, you can create something like the following, which takes an arbitrary class and instantiates it will arbitrary arguments (*args) and keyword arguments (**kwargs):
class Price:
def __init__(self, name, data):
self.name = name
self.data = data
def create_instance(my_class, *args, **kwargs):
return my_class(*args, **kwargs)
def CreateHTML(one_instance):
list_members = list(one_instance.__dict__) ##to get the list of member variables' names
n= len(list_members)
print(f"This instance has {n} members")
one_instance1 = create_instance(Price, name="Hello", data="World")
one_instance2 = create_instance(Price, name=None, data=None)
CreateHTML(one_instance1)
CreateHTML(one_instance2)
You can use create_instance for any class and any arguments, e.g.:
class SomeClass:
def __init__(self, foo, bar):
self.foo = foo
self.bar= bar
one_instance3 = create_instance(SomeClass, "hello", bar="World")
Although to be honest, you don't really gain some much from this. Might as well just use:
one_instance1 = Price(name="Hello", data="World")
one_instance2 = Price(name=None, data=None)
one_instance3 = SomeClass("hello", bar="World")

Python classes: optional argument

I want the user to be able to initiate a class by passing an argument to it, and if he doesn't pass it then it should be automatically created by the class. How is that usually done in Python? Example:
class MyClass(object):
def __init__(self, argument):
self.argm = argument
# logic here: if user does not pass argument
# run some function or do something
def create_argm(self):
self.argm = 'some_value'
object_example = MyClass()
print(object_example.argm) # will print 'some_value'
object_example = MyClass('some_other_value')
print(object_example) # will print 'some_other_value'
Edit : self.argm will be a python-docx Object so i'm unable to do def __init__(self, argument = Document() or am i?
if you cant create the value in the function definition, you can use a value that indicates nothing, luckily python has None so you can do something like:
class MyClass(object):
def __init__(self, argument=None):
if argument is None:
self.argm = self.create_argm()
else:
self.argm = argument
def create_argm(self):
return 'some_value'
if None Doesn't fit because you want that to be a valid value for argument without assuming it was left out you can always create a dummy value:
class MyNone:
pass
class MyClass(object):
def __init__(self, argument=MyNone):
if argument is MyNone:
self.argm = self.create_argm()
else:
self.argm = argument
def create_argm(self):
return 'some_value'
This is usually done with a default value assigned to a key word argument:
class MyClass(object):
def __init__(self, argument='default value'):
self.argm = argument
You have to pay special attention if you want this default value to be a mutable object; this may lead to unwanted behavior, as the object will be created only once, then mutated.

Why is a variable in __init__() method not defined in the subclass?

In subclass ComputerGame, Toy.__init__(self,n), n is undefined.
Why is it warning me that the variable n is undefined when I try to call the __init__() function in the base class? Simply put, why is Toy.__init__(self,n) not callable in the subclass? I have declared ComputerGame (Toy):. Why isn't it inheriting the method Toy.__init__(self,n)?
Should I declare the variable outside the class?
class Toy:
def __init__(self,n):
self.__ToyName = n
self.__ToyID = ""
self.__Price = 0.00
self.__MinimumAge = 4
def SetToyName(self,p):
self.__ToyName = p
def SetToyID(self,d):
self.__ToyID = d
def SetPrice(self,i):
self.__Price = i
def SetMinimumAge(self,i):
self.__MinimumAge = i
def GetToyName(self):
return (self.__ToyName)
def GetToyID(self):
return (self.__ToyID)
def GetPrice(self):
return (self.__Price)
def GetMinimumAge(self):
return (self.__MinimumAge)
class ComputerGame(Toy):
def __init__(self):
Toy.__init__(self,n)
self.__Catogory = ""
self.__Console = ""
def SetCatogory(self,c):
self.__Catogory = c
def SetConsole(self,c):
self.__Console = c
def GetCatogory(self):
return (self.__Catogory)
def GetConsole(self):
return (self.__Console)
This is a scoping issue:
class ComputerGame(Toy):
def __init__(self):
Toy.__init__(self,n)
This is the first appearance of n. When you create a ComputerGame, your __init__ methods requires you (the calling program) to supply n as part of the creation. That's how you wrote the code.
The __init__ above assumes that n will appear magically from nowhere. I'm unclear what data flow you expect from this -- and so is the Python compiler. I don't know how to fix this for you, since you failed to supply a Minimal, complete, verifiable example. We should have at least one line of main code to create the object.
One strong possibility is fairly simple:
class ComputerGame(Toy):
def __init__(self, n):
Toy.__init__(self, n)
NewFPS = ComputerGame("Universal Uzi")
Does that clear it up?

python using __init__ vs just defining variables in class - any difference?

I'm new to Python - and just trying to better understand the logic behind certain things.
Why would I write this way (default variables are in __init__):
class Dawg:
def __init__(self):
self.previousWord = ""
self.root = DawgNode()
self.uncheckedNodes = []
self.minimizedNodes = {}
def insert( self, word ):
#...
def finish( self ):
#...
Instead of this:
class Dawg:
previousWord = ""
root = DawgNode()
uncheckedNodes = []
minimizedNodes = {}
def insert( self, word ):
#...
def finish( self ):
#...
I mean - why do I need to use __init__ -> if I can just as easily add default variables to a class directly?
When you create variables in the Class, then they are Class variables (They are common to all the objects of the class), when you initialize the variables in __init__ with self.variable_name = value then they are created per instance and called instance variables.
For example,
class TestClass(object):
variable = 1
var_1, var_2 = TestClass(), TestClass()
print var_1.variable is var_2.variable
# True
print TestClass.variable is var_1.variable
# True
Since variable is a class variable, the is operator evaluates to True. But, in case of instance variables,
class TestClass(object):
def __init__(self, value):
self.variable = value
var_1, var_2 = TestClass(1), TestClass(2)
print var_1.variable is var_2.variable
# False
print TestClass.variable is var_1.variable
# AttributeError: type object 'TestClass' has no attribute 'variable'
And you cannot access an instance variable, with just the class name.
When you write this:
class Dawg:
previousWord = ""
root = DawgNode()
uncheckedNodes = []
minimizedNodes = {}
Those are not instance variables, they're class variables (meaning: the same variables with the same values are shared between all instances of the class.) On the other hand, this:
class Dawg:
def __init__(self):
self.previousWord = ""
self.root = DawgNode()
self.uncheckedNodes = []
self.minimizedNodes = {}
... Is declaring instance variables, meaning: the values are different for each instance of the class. As you see, each snippet means a completely different thing, and you have to pick the one that is appropriate for you. Hint: most of the time you're interested in instance variables, because class variables define a kind of shared global state for your objects, which is error prone.

TypeError in Python 3.x

I have no idea what is wrong! This is a very simple program and I have done a lot head banging! Please someone enlighten me!
This a lab problem from the CSE 111 - Programming Language II course. They teach Java at the university and the code I wrote in Java works fine.
I just have to create a Student class with some fields to hold the basic information about a student with methods to get and set the attributes. Then create an instance of that class and tryout the methods.
But every time I run this program the following error occurs:
TypeError: set_name() takes exactly 1 positional argument (2 given)
Here is the code I wrote.
class Student:
'''Student class'''
name = None
id = 0
address = None
cgpa = None
def get_name():
return name
def set_name(n):
name = n
def get_id():
return id
def set_id(i):
id = i
def get_address():
return address
def set_address(a):
address = a
def get_cgpa():
return cgpa
def set_cgpa(c):
cgpa = c
#An object of Student class
jack = Student()
jack.set_name('jacky')
print(jack.get_name())
You're not accepting a reference to your instance as the first argument to that method, i.e. your set_name() should be written:
def set_name(self, n):
self.name = n
This is somewhat different from other languages where there is a built-in keyword (such as this) that refers to the current object. Python passes that reference explicitly, as an argument to the method.
All your other methods must be modified similarly.
Note that just setting name = n sets a local variable name which goes away when the method ends; it does not set anything on the instance. You have to explicitly set self.name if you want an instance attribute.
Also, and this is a matter of style, but you do not usually write set and get methods in Python. It is normal practice to set and get attributes directly. If you want to do validation of values, use a property instead. So basically, none of your methods are actually necessary in good style.
However, you don't have an __init__() method. Usually you would pass the desired attributes of the instance when instantiating the class and save these on the instance.
class Student:
def __init__(self, name, id, address, cgpa):
self.name = name
self.id = id
self.address = address
self.cgpa = cgpa
herman = Student("Herman Munster", 12345, "1313 Mockingbird Lane", 4.0)
Try this:
import sys
class Student:
'''Student class'''
self.name = None
self.id = 0
self.address = None
self.cgpa = None
def get_name(self):
return self.name
def set_name(self, n):
self.name = n
def get_id(self):
return self.id
def set_id(self, i):
self.id = i
def get_address(self):
return self.address
def set_address(self, a):
self.address = a
def get_cgpa(self):
return self.cgpa
def set_cgpa(self, c):
self.cgpa = c
You need to pass self as the first argument to each member function of the class. Member variables must then be referred to with self, i.e. self.name. Furthermore, you may wish to include an __init__() function; this serves usually to initialize any member variables, and is called at the instantiation of the class.
Take a look at the Python documentation here for some examples on well-formed classes: http://docs.python.org/tutorial/classes.html#random-remarks
In Python, you need to pass in self for each of your member functions. You also need to reference class variables as self.x, if you want them to take an effect.
Here are a couple examples that you need to apply to the rest of your code.
def set_name(self, n):
self.name = n
def get_cgpa(self):
return self.cgpa
There is some explanation for why this is the case in the documentation.
This is because first argument of methods is self - the class instance.
See What is the purpose of self?
and http://docs.python.org/tutorial/classes.html#class-objects

Categories

Resources