Ex36: "NameError: name 'self' not defined": Edited

Edit: I learned something. I completely misunderstood how to construct classes in Python. What confused me is that there seems to be redundant code with Python. I have a question about that, and then I think I can marked this solved.

So, here’s my code that I used to test this out:

class PaintMe():

	color = None
	
	def __init__(self, color):
		self.color = color

	this_is_the_color = color
	
	def what_is_the_color(self):
		print (self.color)
		
Painting = PaintMe(color = "Blue")
Painting.what_is_the_color()

What is majorly confusing me is, why is there a
“self.color = color”
line at all? Isn’t that completely superfluous, redundant, self referential, and unnecessary? That was what threw me off. It confused my brain right out my rear end. I assumed, looking at example code of classes, that you would use that line to pass the argument “color” to a variable of your choosing with whatever name you decide.

Like, for example,
“file_name = self.file”, where “file” is passed as an argument in the class.

I figured out how to fix my code, but it only begs more questions. Why is that line even necessary?



</ EDIT>



Quick explanation: in Exercise 36 we’re challenged with making a text based adventure. I am just adding a few extra things for fun, like the ability to find a piece of armor that has stats. The stats are read from a text file. I am putting it into a class in case I want to make multiple pieces of armor. I’m having trouble figuring out classes.

According to the entirety of the internet and Python documentation, I should be able to define class variable things in

def __init__(self, variable):
    self.thing = variable

variablething = self.thing

But with that code, I get the error “NameError: name ‘self’ not defined”. What’s that deal?

My research shows that it means that ‘self’ hasn’t been declared yet, but of course it has, it’s a specially reserved part of Python. This code throws the same error in Python 2.7.13 and 3.6.2.

file_target = 'leatherarmor.txt'

class Magic():
	FROS = 0.0
	FIRE = 0.0
	POIS = 0.0
	STOR = 0.0
	WATE = 0.0
	EART = 0.0
	DARK = 0.0
	LIGH = 0.0
	MADN = 0.0
	VOID = 0.0
	
class Armor(object):
	def __init__(self, file):
		self.file = file
	
	file_name = self.file
	armor_file = open(file_name)	
	file_lines = armor_file.readlines()
		
	ARM = 0
	DUR = 0.00
	DEX = 0
	LVL = 0
	STA = 0.00
	WEI = 0.0
	VAL = 000.00
	MAG = False
	SOK = False
	NSK = 0
	GEM = None
	TMAG = Magic()
	
	for line in file_lines:
		temp_line = line
		temp_atr = line[:3]
		
		if (temp_atr == "ARM"):
			ARM = int(temp_line[6:])
		elif (temp_atr == "DUR"):
			DUR = float(temp_line[6:])
		elif (temp_atr == "DEX"):
			DEX = int(temp_line[6:])
		elif (temp_atr == "LVL"):
			LVL = int(temp_line[6:])
		elif (temp_atr == "STA"):
			STA = float(temp_line[6:])
		elif (temp_atr == "VAL"):
			VAL = float(temp_line[6:])
		elif (temp_atr == "MAG"):
			MAG = bool(temp_line)
			if (MAG == True):
				magic_filename = armor_file.name[:-4] + ".mag.txt"
				print (magic_filename)
				mag_file = open(magic_filename)
				TMAG = Magic()
				for mag_line in mag_file.readlines():
					print (mag_line)
		elif (temp_atr == "SOK"):
			SOK = bool(temp_line)
		elif (temp_atr == "NSK"):
			NSK = float(temp_line[6:])
		elif (SOK == True):
			GEM = [] * NSK

leather_armor = Armor()

TEXT FILE #1 - leatherarmor.txt


ARM = 15
DUR = 75.00
DEX = -5
LVL = 3
STA = 0.94
WEI = 12.5
VAL = 121.43
MAG = True


TEXT FILE #2 - leatherarmor.mag.txt


FROS = 0.0
FIRE = 0.0
POIS = 0.0
STOR = 0.0
WATE = 0.0
EART = 0.0
DARK = 0.0
LIGH = 0.0
MADN = 0.0
VOID = 0.0

Well, it’s kind of redundant, but that’s how Python decided to do their classes. In other languages there’s something similar to indicate “The current object”. In java, javascript, and others it’s the word this. In Ruby and Perl it’s a symbol, like @. In python they explicitly use a variable added to a function can call it self.

In a way, it’s kind of something you just have to put up with when you code with Python. No point tilting at windmills.