Python Forum
understanding lists....I'm very confused
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
understanding lists....I'm very confused
#1


I'm trying to get a grasp on how lists behave. I've included two VERY simple .py programs. I'm trying to get comfortable using oop (I can do blunt code...but oop trips me up...)

my question is can anyone explain how is python treating the lists? In one program I instantiate the list in the class...in the second program I do not. The only thing I can think of is I need to instantiate in class0.py __init__ func when the list is such that it will take in user's input? idk if this explanation is correct

I've better elaborated my question in the code comment...please help. Thx && HAPPY HOLIDAYS!!!!!

#class0.py
class Sur():
	def __init__(self):
		self.things = [] #pls note list is instantiated...but in class1.py I don't use it?
	def add_info(self,new_ish):
		self.things.append(new_ish)
		print('added:',new_ish)
		return new_ish
	def print_all(self):
		for j in self.things:
			print(j)

#run0.py
from class0 import Sur
Surv=Sur()
listt=[] #instantiated here as well since list exists in __init__
for i in range(1,2):
	incoming = str(input('> '))
	if incoming == 'q' or incoming =='':
		break
	else:
		Surv.add_info(incoming)
Surv.print_all()
#class1.py
import random
class Die():
	def __init__(self,sides=6):
		self.sides = sides
        #notice there is no instantiation of list in this file 
        #QUESTION IS WHY IS THIS????

	def roll(self,turn):
		self.turn = random.randint(1,self.sides)
		return self.turn		
#run1.py
from class1 import Die
foo =Die()
results = []#why isn't there a list in class1  ---IDU this!!!

for i in range(1,2):
	drop = foo.roll(i)
	results.append(drop)
	print(str(i)+']'+str(drop))
Reply
#2
#class1.py
import random
class Die():
    def __init__(self,sides=6):
        self.sides = sides
        #notice there is no instantiation of list in this file 
        #QUESTION IS WHY IS THIS????
 
    def roll(self,turn):
        self.turn = random.randint(1,self.sides)
        return self.turn        
There is no list because you didn't put one there! Why do you think there should be one?

What is supposed to be happening that isn't or what, specifically, isn't working correctly?
Reply
#3
Quote:There is no list because you didn't put one there! Why do you think there should be one?

It's a variable that can be passed into other functions of the class as it is in class0.py
But if I declare it in class1.py, then run1.py breaks.

If class1.py reads
#class1.py
class Die():
   def __init__(self):
      self.results = []
   --snip--
NOW run1.py won't run.

At the same time for run0.py to work I MUST declare a [] in class0.py like so:
#class0.py
class Sur():
   def __init__(self):
      self.result = []
   --snip--
To restate my question ...why MUST I declare a [] list in class0.py and NOT declare it in class1.py I would think that based on pythons rules I must declare such variables in the class constructor. What is it about class1.py that is an exception to this logic?

Restating in, yet, another way, I MUST declare a [] in class0.py for run0.py to work. But I must NOT declare a [] in class1.py. If I do declare a [] in class1.py then run1.py. So declaring [] in class0.py is mandatory. Not declaring [] in class1.py is mandatory? I don't understand why...


When do I need to explicitly define a [] variable in the object constructor and when do I not? I have two very simple programs....one breaks if I define the [] variable. The other breaks if I DON'T define the [] variable....

IDK how to simplfy this q further....please help
Reply
#4
You need to show the complete code that doesn't work.

In general, you can declare variables (also called fields) in classes that are "local" to that class. In your examples, the Sur class in class0.py declares a result field and initializes it as a list:

class Sur:
    def __init__(self):
        self.result = []  # this creates a field/variable and initializes it as a list

    def add_result(self, value):
        self.result.append(value)  #other class methods can then refer to the same variable to get work done.
So now when you create a Sur object, and add results to the list, you save each result in a list.

The Die class (the names of the files are irrelevant to this discussion) doesn't need a list as a class member. It stores how many sides/faces the die has and then "rolls".

If you wanted, you should be able to declare a list in the Die class and store past rolls:

#class1.py
import random
class Die():
    def __init__(self,sides=6):
        self.sides = sides
        self.past_rolls = []  # my added list
 
    def roll(self,turn):
        self.turn = random.randint(1,self.sides)
        self.past_rolls.append(self.turn)
        return self.turn        
I haven't run this code but it should work fine.

Again, please post the COMPLETE BROKEN code so I (or someone else) can better answer why your code doesn't work.
Reply
#5
Quote:You need to show the complete code that doesn't work.

In general, you can declare variables (also called fields) in classes that are "local" to that class. In your examples, the Sur class in class0.py declares a result field and initializes it as a list:

I'm just not able to conceptualize list in oop. I get the codes to work (by debugging & trial/error) but the logic confuses me...especially with list in constructor methods...ijdu

for example this code works...I'm faithful to keeping each function simple and doing 1 single task. please see code comments for my questions pertaining to the [].
#class.py
import random

class Die():
	def __init__(self,sides=6):
        #here are my instance variables(object characteristics come from these) AKA attributes/fields
        #[] is treated as an attribute(field) Why?  it should not be but it is
        #why? (obviously I can memorize this as an exception to the rule (lists and fields in __init__) it's fine...i just don't understand the why...
		self.sides = sides
		self.throws=[]

	def roll(self,turn):#turn field doesn't 'exist' prior to this method.
		#so no pt in defining in constructor method...I sort of understand this...it's fine
		self.turn = random.randint(1,self.sides)#random is inclusive, range is excl. pretty annoying
		return self.turn
	def update_rolls(self):
		self.throws.append(self.turn)
		return self.throws
	def print_list(self):
		for t in self.throws:
			print('die is -',t)
#run.py

from class import Die

die = Die()
results=[]#if I delete this I get an attribute error that die obj has no attribute named update_rolls.
#update_rolls is a method not an attribute.It just uses the [] attribute

for i in range(1,3):
	t=die.roll(i)
	die.update_rolls() #so this is a func...clearly...but if I delete results =[] python thinks update_rolls() is intended as attribute?
die.print_list()
Maybe I'm overthinking this but why is my list a field (in __init__)? Is it because my other methods use it? If I create all class variables in the constructor method why can I create the variable 'turn' in the roll() method? Basically I am forced to create list[] in __init__ but all other fields through any function? Very confused...
Reply
#6
First off, don't call any file "class.py" that's just going to cause you all sorts of problems.

(Dec-23-2017, 02:38 AM)mepyyeti Wrote:
Quote:You need to show the complete code that doesn't work.

In general, you can declare variables (also called fields) in classes that are "local" to that class. In your examples, the Sur class in class0.py declares a result field and initializes it as a list:

I'm just not able to conceptualize list in oop. I get the codes to work (by debugging & trial/error) but the logic confuses me...especially with list in constructor methods...ijdu

for example this code works...I'm faithful to keeping each function simple and doing 1 single task. please see code comments for my questions pertaining to the [].
#class.py
import random

class Die():
	def __init__(self,sides=6):
        #here are my instance variables(object characteristics come from these) AKA attributes/fields
        #[] is treated as an attribute(field) Why?  it should not be but it is
        #why? (obviously I can memorize this as an exception to the rule (lists and fields in __init__) it's fine...i just don't understand the why...
		self.sides = sides
		self.throws=[]

	def roll(self,turn):#turn field doesn't 'exist' prior to this method.
		#so no pt in defining in constructor method...I sort of understand this...it's fine
		self.turn = random.randint(1,self.sides)#random is inclusive, range is excl. pretty annoying
		return self.turn
	def update_rolls(self):
		self.throws.append(self.turn)
		return self.throws
	def print_list(self):
		for t in self.throws:
			print('die is -',t)

You say, "[] is treated as an attribute". This is incorrect. self.throws is the attribute; you are simply initializing it to be an empty list. To put it another way, self.throws is an attribute of type "list".

Quote:
#run.py

from class import Die

die = Die()
results=[]#if I delete this I get an attribute error that die obj has no attribute named update_rolls.
#update_rolls is a method not an attribute.It just uses the [] attribute
This is simply not true. I can say that without running the code, but I also ran the code with and without the results list defined and it works either way.

Again, don't name any file "class.py". "class" is a keyword in Python and saying "from class import X" doesn't work.


Quote:Maybe I'm overthinking this but why is my list a field (in __init__)? Is it because my other methods use it?
Exactly. It's good programing to declare and initialize your class variables/fields/attributes in your constructor. You don't have to in Python, but it's a good idea.

Quote: If I create all class variables in the constructor method why can I create the variable 'turn' in the roll() method?
Because Python lets you. I would argue that it's not good practice but it's allowed by the language.

Quote: Basically I am forced to create list[] in __init__ but all other fields through any function? Very confused...

No, you don't have to initialize throws in the constructor but you do have to initialize it before calling self.turns.append().

Here are my files:

#class1.py

import random
 
class Die():
    def __init__(self,sides=6):
        #here are my instance variables(object characteristics come from these) AKA attributes/fields
        #[] is treated as an attribute(field) Why?  it should not be but it is
        #why? (obviously I can memorize this as an exception to the rule (lists and fields in __init__) it's fine...i just don't understand the why...
        self.sides = sides
        self.throws=[]
 
    def roll(self,turn):#turn field doesn't 'exist' prior to this method.
        #so no pt in defining in constructor method...I sort of understand this...it's fine
        self.turn = random.randint(1,self.sides)#random is inclusive, range is excl. pretty annoying
        return self.turn
    def update_rolls(self):
        self.throws.append(self.turn)
        return self.throws
    def print_list(self):
        for t in self.throws:
            print('die is -',t)
#run.py
 
from class1 import Die
 
die = Die()
#results=[]#if I delete this I get an attribute error that die obj has no attribute named update_rolls.
#update_rolls is a method not an attribute.It just uses the [] attribute
 
for i in range(1,3):
    t=die.roll(i)
    die.update_rolls() #so this is a func...clearly...but if I delete results =[] python thinks update_rolls() is intended as attribute?
die.print_list()
bash-3.2$ python3.6
Python 3.6.3 (v3.6.3:2c5fed86e0, Oct  3 2017, 00:32:08) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import run
die is - 6
die is - 3
>>> 
Reply
#7
Quote:don't name any file "class.py". "class" is a keyword in Python and saying "from class import X" doesn't work.
it was used as a place holder for the post...in the actual program file is something like a.py. Thought it would be clearer to use something descriptive like 'class.py' in the snippet...apologies.

Quote:You say, "[] is treated as an attribute". This is incorrect. self.throws is the attribute; you are simply initializing it to be an empty list. To put it another way, self.throws is an attribute of type "list".
ok...I suppose my jibe is with the naming convention here:
class foo():
   def __init__(self, bar):
      self.moo = bar #technically this 'runs' 
      #and visually someone starting out may misconstrue that attribute=parameter (bar in this case)
      #but self.moo is really the attribute.  WHY AM I ALLOWED to name self.moo as anything I want? 
      #what is the rationale here?  It really should be self.bar = bar...and this is convention, but         
      #nothing really stops us from changing attr to self.moo 
Quote:I can say that without running the code, but I also ran the code with and without the results list defined and it works either way.
You are right. I also tried it and it works. I want to ask why do you run directly through bash? what is the advantage? I ask bc I started out coding directly through the terminal (linux) -but didn't like it. Moved to idle, and now go through geany (atom feels buiky). Any advantage to running thru bash(or terminal) and python3 vs geany (& other ides)f5???

thanks...growing pains I guess...unfortunately there are no truly viable online communities for noobs...it's a shame...thanks again.
Reply
#8
class foo():
   def __init__(self, bar):
      self.moo = bar #technically this 'runs' 
      #and visually someone starting out may misconstrue that attribute=parameter (bar in this case)
      #but self.moo is really the attribute.  WHY AM I ALLOWED to name self.moo as anything I want? 
      #what is the rationale here?  It really should be self.bar = bar...and this is convention, but         
      #nothing really stops us from changing attr to self.moo 
It is extremely common in ALL languages to use attribute names that are different from the parameters that set them. Other OOP languages support "data hiding" where attributes/fields are not directly accessible. Python does not have this. In other words, using your example I could do this:

class Foo:
    def __init__(self, bar):
        self.moo = bar


f = Foo()
f.moo = "MOOOOOOOOO"
So in Python we follow a convention where we put an underscore '_' in front of fields that shouldn't be touched:

class Foo:
    def __init__(self, bar):
        self._moo = bar
So why does the language let you? Because all you're doing is assigning the value of one variable (bar) to another (self._moo). The language itself doesn't (and can't) attribute semantic meaning to variable names. It's up to you, the programmer to write clear, clean, and understandable code. And I will let you in on a little secret: lots of programmers write muddled, ugly, unintelligible code. But it works so they think they're a success.

Quote: I want to ask why do you run directly through bash? what is the advantage? I ask bc I started out coding directly through the terminal (linux) -but didn't like it. Moved to idle, and now go through geany (atom feels buiky). Any advantage to running thru bash(or terminal) and python3 vs geany (& other ides)f5???

I do the bulk of my development work with Vim and bash simply because I'm very comfortable with those tools. I use and like PyCharm, and have used Eclipse and Visual Studio for Java and C/C++/C# development as well. In this particular case, to copy and paste a little code and run it quickly, there was no reason to fire-up an IDE.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Confused with 'flags' tester_V 10 1,011 Apr-12-2021, 03:03 AM
Last Post: tester_V
  Simple Tic Tac Toe but I'm confused Izith 1 531 Sep-26-2020, 04:42 PM
Last Post: Larz60+
  I am really confused with this error. Runar 3 661 Sep-14-2020, 09:27 AM
Last Post: buran
  Confused by 'break' in the official documents Chuck_Norwich 2 764 Apr-12-2020, 09:26 PM
Last Post: Chuck_Norwich
  Confused on how to go about writing this or doing this... pythonforumuser 3 866 Feb-10-2020, 09:15 AM
Last Post: snippsat
  I always get 'None' returned. Confused. What did I miss? jpezz 2 977 Apr-07-2019, 10:06 AM
Last Post: jpezz
  Confused by order of operations ward 4 1,158 Jan-22-2019, 08:53 PM
Last Post: Larz60+
  Confused by this modulo equation VikramSuh 3 1,345 Sep-05-2018, 12:43 PM
Last Post: VikramSuh
  Help in understanding scope of dictionaries and lists passed to recursive functions barles 2 1,528 Aug-11-2018, 06:45 PM
Last Post: barles
  I am new to python , i am confused with this syntax , please help aankrose 3 1,294 Aug-03-2018, 06:49 PM
Last Post: aankrose

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020