Using a @classmethod will be the easiest alternative for that.
class UserInput: # capitals! Look at PEP 8. users = [] # rearranged to the top for better readability def __init__(self, name, lista, listb, listc, listd): self.name = "" self.lista = lista self.listb = listb self.listc = listc self.listd = listd @classmethod def create_new_user(cls): # no need for x if you overwrite it immediately x = cls("x", "", "", "", "") cls.users.append(x) # easier access to this static attribute return x # for the caller having access to it as well.
It works as well if we subclass UserInput as it uses the new class then.
But note that x = cls("x", "", "", "", "") won't be very useful, though; better do
@classmethod def create_new_user(cls, *a, **k): # no need for x if you overwrite it immediately x = cls(*a, **k) # pass the arguments given by the caller to __init__. cls.users.append(x) # easier access to this static attribute return x # for the caller having access to it as well.
I can use that now this way:
a = UserInput("foo", "whatever", "is", "needed", "here")
or, if I choose to,
a = UserInput.create_new_user("foo", "whatever", "is", "needed", "here")
which additionally appends the new user to the list.
If you want to be able to shorten the arguments list, you can do so as well:
def __init__(self, name, lista=None, listb=None, listc=None, listd=None): self.name = name self.lista = lista if lista is not None else [] self.listb = listb if listb is not None else [] self.listc = listc if listc is not None else [] self.listd = listd if listd is not None else []
if they are really lists. If they are strings, another name would be appropriate and, as strings are immutable, you can simply do
def __init__(self, name, lista='', listb='', listc='', listd=''): self.name = name self.lista = lista self.listb = listb self.listc = listc self.listd = listd
and call the stuff with
a = UserInput.create_new_user("foo", listc=...) # all others are left empty b = UserInput("bar") # all are left empty c = UserInput.create_new_user("ham", lista=..., listd=...) # all others are left empty
Now that you come up with a different task, I'll try to cope with that as well:
@classmethod def create_new_users(cls): # several users! print("how many users do you want to create") num = int(input()) for _ in range(num): # simpler iteration print("enter the user's name") name = input("") # in 3.x, this is always a string, so it cannot be None... # if name == "" or "None,none": # That won't work as you think. if name == '' or name.lower() == 'none': # but why disallow the string 'None'? # raise SyntaxError("name cannot be None or empty") raise RuntimeError("name cannot be None or empty") # or ValueError or alike # break not needed. raise jumps out without it as well. user = cls(name, "", "", "", "") # name is an input, not an output. cls.users.append(name)
But I wonder if the class is really the right place to store new users, and only those created with this function. Maybe it would be better to feed the users list directly in __init__ and let this function be at a higher level.
The advantage of using a @classmethod here is that you always work on the corret basis.
Imagine you have a UserInput with a __init__() method as above. Then you can subclass it and do
UserInput.create_new_users()Using a @classmethod will be the easiest alternative for that.
class UserInputStoring(UserInput): users = [] # this is only here, not at the parent. def __init__(self, *a, **k): super(UserInputStoring, self).__init__(*a, **k) # pass everything up as it was used self.users.append(self)
Now you can have your create_new_users() in the base class and be a @classmethod and it will pick the right __init__ to call depending on how you call it.
tim=userinput("foo","","","","");does not create a class, but an instance of it. The class is created as soon as theclass ...:body is executed.