Why is this simple python class not working? - python

I'm trying to make a class that will get a list of numbers then print them out when I need. I need to be able to make 2 objects from the class to get two different lists. Here's what I have so far
class getlist:
def newlist(self,*number):
lst=[]
self.number=number
lst.append(number)
def printlist(self):
return lst
Sorry I'm not very clear, I'm a bit new to oop, can you please help me cos I don't know what I'm doing wrong. Thanks.

In Python, when you are writing methods inside an object, you need to prefix all references to variables belonging to that object with self. - like so:
class getlist:
def newlist(self,*number):
self.lst=[]
self.lst += number #I changed this to add all args to the list
def printlist(self):
return self.lst
The code you had before was creating and modifying a local variable called lst, so it would appear to "disappear" between calls.
Also, it is usual to make a constructor, which has the special name __init__ :
class getlist:
#Init constructor
def __init__(self,*number):
self.lst=[]
self.lst += number #I changed this to add all args to the list
def printlist(self):
return self.lst
Finally, use like so
>>> newlist=getlist(1,2,3, [4,5])
>>> newlist.printlist()
[1, 2, 3, [4,5]]

You should use "self.lst" instead of "lst". Without the "self", it's just internal variable to current method.

Related

Calling methods directly from a list filled with objectsA from objectB in python 3.7

I'm trying to call methods from a list that is filled with objects from a different class where the list is defined.
Consider the following:
class ObjectA(object):
def __init__(self, object_id):
self.id = object_id
def a_function(self):
return self.id
from ObjectA import ObjectA
class ObjectB:
def test():
object_1 = ObjectA(1) # passing the id
a_list = [ObjectA] # setting the list to be of type ObjectA (?)
a_list.append(object_1)
a_list[0].a_function() # Says I need to pass argument 'self'
How something like this would be possible? I know that I could instead do a_list[0].id and it works but it feels wrong. I prefer having setters/getters.
Edit: I'm also aware that if I declare the list like this a_list = [] instead of a_list = [ObjectA] it also works but in that case I don't have access to the methods for autocompletion.
In Python you can't specify the type of a list. So the line a_list = [ObjectA] makes no sense. (In fact it creates a list containing the class ObjectA, not an object, hence the self error.)
Replace a_list = [ObjectA] with a_list = [] to create an empty list

infinite recursion when printing instance in python

I get a Runtime error (maximum recursion) when I execute the following code.
I'm trying to generate a list of instances; then I would like to print each one. I'm not sure what's going on here.
Anyway, what is the correct way to access each instance from the instance list?
I do realize I'm using a string of digits to name the instances and this is not cool. But say each number on the list is associated with a bunch of information. Then having attributes for each could make things accessible. I tried using a dict but I end up with nested dicts and I just didn't like it.
Thanks in advance.
class MyClass(object):
def __str__(self):
stuff= str(self)
return stuff
mylist = ['1234567','8910111','1213144','7654321']
inslist = [MyClass() for i in mylist]
print inslist[0]
The problem is in your __str__. If you call str(self), it will call itself. I think you meant was this:
class MyClass(object):
def __init__(self, i):
self.i = i
def __str__(self):
return str(self.i)
mylist = ['1234567','8910111','1213144','7654321']
inslist = [MyClass(i) for i in mylist]
print inslist[0]

assignment overriden to keep changing original instance variable in Python class

Basically, this is what the problem is. I have a class with an optional parameter: lst. lst is a nested list. Below is a method that returns another instance of the class that it is inside.
self.lst = [[[1, 2]]] # this is defined in the constructor
s = self.lst
for a in s:
for b in a:
if b[0] != item:
b[0] = 5
return ChangeNumb(lst=s)
What happens after this is VERY weird. Returning ChangeNumb.lst is now [[[5, 2]]], but the class that the method is run in ALSO ChangeNumb.lst == [[[5, 2]]].
So that instead of just returning a new instance of a class with a different parameter, this method changes the self.lst of the class it is inside as well.
I need to make it so that self.lst does not change, while returning a new instance.
PLEASE HELP
EDIT: Although I've encountered a similar problem when writing the class constructor, I was able to resolve it as -> self.lst = lst.copy(); however, s = self.lst.copy() does not work!
You have to make a copy in order not to modify self.lst.
For simple lists just list() is enough, but as you have nested lists you should use copy.deepcopy().
So you could change your declaration with something like :
s = copy.deepcopy(self.lst)

What is the proper way to share a list between class instances?

I have this example code
my_list = ["a","b","c","d"]
class A:
def __repr__(self):
return ', '.join(my_list)
def add(self, num):
my_list.append(num)
class_list = []
for x in range(5):
class_list.append(A())
class_list[x].add("class_%s" % (x))
print class_list[x]
The non-example code of mine is more complicated, but the idea is that I have multiple instances of the classes off doing a "thing". The global my_list is utilized across all instances. When certain logic is met within a class, that instance will modify the list. The rest of the classes will utilize that list to perform their logic as well. Any instance can add to the list, and all instances should be able to utilize the updated value.
Now in this example, the my_list is shared, but is this the correct way to do it?
A class attribute is usually better than a global, because then they're just sharing it with each other, rather than with everyone in the world.
To do that, move the my_list = ["a","b","c","d"] line under the class A:, and change every reference to my_list to self.my_list or A.my_list:
class A(object):
shared_list = []
def add(self, num):
self.my_list.append(num)
However, an instance attribute is often even better. If you assign the same list to a bunch of different variables, it's still just one list; changing it affects all those variables. So, you can do something like this:
class A(object):
def __init__(self, shared_list):
self.shared_list = shared_list
def add(self, num):
self.shared_list.append(num)
Now it's up to the code that uses the A objects to decide whether to give them all the same list. You can even create 20 instances that share one list, and 10 that share a different one:
list1 = []
group1 = [A(list1) for _ in range(20)
list2 = []
group2 = [A(list2) for _ in range(10)
The question is whether the caller, or the A class, or nobody at all is the one who should be making the decision of how "shared" the list is. The answer is different for different applications, so it's hard to give an answer for an abstract example with names like A and my_list.

Understanding python variable scope within class

I am trying to define a variable in a class that then can be accessed/changed from functions within that class.
For example:
class MyFunctions():
def __init__( self):
self.listOfItems = []
def displayList( self):
"""Prints all items in listOfItems)"""
for item in self.listOfItems:
print item
def addToList(self):
"""Updates all mlb scores, and places results in a variable."""
self.listOfItems.append("test")
f = MyFunctions()
f.addToList
f.displayList
This should output all of the items in the list for me, but instead it displays nothing. I am assuming this is occuring because I did not setup the scope of the variables correctly. I want to be able to access and change listOfItems from within all of the functions in MyFuctions.
I have been trying to figure this out for a few hours now, so any help would be greatly appreciated.
f.addToList and f.displayList do not invoke the methods addToList and displayList respectively. They simply evaluate to the method (bound to the object f in this case) themselves. Add parentheses to invoke the methods as in the corrected version of the program:
class MyFunctions():
def __init__( self):
self.listOfItems = []
def displayList( self):
"""Prints all items in listOfItems)"""
for item in self.listOfItems:
print item
def addToList(self):
"""Updates all mlb scores, and places results in a variable."""
self.listOfItems.append("test")
f = MyFunctions()
f.addToList()
f.displayList()
This is in contrast to Ruby which does not require parentheses for method invocation (except to eliminate ambiguity in certain cases).
It is instructive to add the following to the end of your program:
print type(f.addToList)
This will output something like the following:
<type 'instancemethod'>
demonstrating that this is a method reference and not a method invocation.

Categories