I was researching how classes work and I figured out how to make a class work in some scenarios. But I couldn't find a way in which to make my scenario work. It involves class Function():
, def __init__(self):
, and def AnotherFunction(self, Foo):
. Those aren't the actual "Functions" in my scenario but, they are very similar. Here is my code:
class Name():
def __init__(self, Name):
self.Name = ["Your Dicer's name is: "]
self.AddName()
def AddName(self):
self.Count = 1
while(self.Input == 1):
Input = input("What is your Dicer's name?:\n")
if(any(BadWord in Input.lower() for BadWord in [])):
print("That's an inappropriate name! Try again")
elif(len(Input) < 3):
print("That name is too short! Try again.")
elif(len(Input) > 16):
print("That name is too long! Try again.")
else:
self.Count -= 1
self.Name.append(Input)
My question is, why wont the while loop
occur in class
? I tried looking up other stack overflow questions, class article and tutorials, and other questions related to while loops but to no avail. Can you tell me why it wont run and how to fix this? I would appreciate that. Thanks! :)
Update 1: I put Input
in the AddName parameters
. I also added Name
as an instance
. But these updates didn't work.
Update 2: I took Input
out of the AddName parameters
. I also changed self.Input
to self.Count
so it doesn't get confusing. I also changed self.Name += Input
to self.Name.append(Input)
. These updates made the code somewhat easier to understand and fixed some of the problems but, the while loop
wont run.
The immediate issue is on these lines:
self.AddName()
def AddName(self, Input):
The second one shows that the AddName
expects one argument in addition to self
. The previous line however, is a call that doesn't pass any argument. You need to make those two match up properly.
I think in this case, you don't need an Input
parameter for AddName
. The Input
variable you're using in the function comes from user input (the input
function), and the argument is completely ignored. (Note, there's also a self.Input
attribute, which is unrelated other than having a very confusingly similar name).
Here's a minimally fixed version:
class Name():
def __init__(self):
self.Name = ["Your Dicer's name is: "]
self.AddName()
def AddName(self): # no Input paramter needed on this line!!!!
self.Input = 1
while(self.Input == 1):
Input = input("What is your Dicer's name?:\n")
if(any(BadWord in Input.lower() for BadWord in [])):
print("That's an inappropriate name! Try again")
elif(len(Input) < 3):
print("That name is too short! Try again.")
elif(len(Input) > 16):
print("That name is too long! Try again.")
else:
self.Input -= 1
self.Name += Input # you may want self.Name.append(Input) here
This "works" in the sense that it doesn't raise an exceptions, but it probably doesn't quite do what you want. The last line, self.Name += Input
appends each character of the inputted name onto the list self.Name
. That's not very useful. Probably you want self.Name.append(Input)
or maybe self.Name
shouldn't be initialized to be a list in __init__
.
There are also a vast number of style issues with this code. I'd strongly recommend renaming all of the variables and attributes. Normal Python style is to use lowercase_names_with_underscores
for functions, methods, attributes and most variables. Only classes have CapitalizedNames
. The self.Input
attribute you're using is also confusingly similar to the local variable Input
while they don't really mean anything very close to one another (there's also no need for self.Input
to be an instance attribute, rather than a local variable of some kind).
Here's a rewrite of your code that doesn't do much different, but has much better style:
class Name():
def __init__(self):
while True:
name = input("What is your Dicer's name?:\n")
if(any(bad_word in name.lower() for bad_word in [])):
print("That's an inappropriate name! Try again")
elif(len(name) < 3):
print("That name is too short! Try again.")
elif(len(name) > 16):
print("That name is too long! Try again.")
else:
self.name = name
break
def __str__(self):
return "Your Dicer's name is: {}".format(self.name)
If you're going to call the AddName
method just once from __init__
, there may not be much point in having it be a separate function. Here I've just merged it right in to __init__
. I've also done away with self.Input
, in favor of a while True
loop, and use break
to exit it when we get a valid name. The potentially invalid name is being stored in a variable named name
rather than Input
, and I've moved the "Your Dicer's name is"
text to the __str__
method, rather than having it be part of the name
attribute.
But I'm not really sure why you're using a class here in the first place. Usually a class represents a concrete "thing" that exists in your program. A Name
is a very abstract sort of "thing". While it's not always unreasonable to have a Name
class, more often, a name
would simply be an attribute attached to some other object (like a Dicer
, perhaps, whatever that is).