1

In most of the examples I have seen online while (trying to) learn classes, the instances of the classes are defined by the programmer. Are there any ways of creating an instance of a class where it the variable that stores the class is defined by the user?

This is an example of an object from another SO question:

class StackOverflowUser:
    def __init__(self, name, userid, rep): 
        self.name = name
        self.userid = userid
        self.rep = rep

dave = StackOverflowUser("Dave Webb",3171,500)

How can this be changed so that the user can create instances based off of the class?

Joseph Farah
  • 2,463
  • 2
  • 25
  • 36
  • Why do you think the user can't *currently* *"create instance based off of [sic] the class"*? What kind of user? Do you mean taking input from the terminal (see e.g. http://stackoverflow.com/q/24986072/3001761)? – jonrsharpe Sep 22 '15 at 16:07
  • Why does the `StackOverflowUser` instance for Dave _need_ to be named `dave`? An instance doesn't even need a name, eg if you have a `list` or `dict` of instances. – PM 2Ring Sep 22 '15 at 16:21

2 Answers2

13

There are broadly two ways of doing it, either:

  1. Have the input entirely outside the class, and just pass it in to __init__ as normal:

    user = StackOverflowUser(
        raw_input('Name: '),
        int(raw_input('User ID: ')), 
        int(raw_input('Reputation: ')),
    )
    

    which is arguably a simpler concept; or

  2. Take input within the class, e.g. using a class method:

    class StackOverflowUser:
    
        def __init__(self, name, userid, rep): 
            self.name = name
            self.userid = userid
            self.rep = rep
    
        @classmethod
        def from_input(cls):
            return cls(
                raw_input('Name: '),
                int(raw_input('User ID: ')), 
                int(raw_input('Reputation: ')),
            )
    

    then call it like:

    user = StackOverflowUser.from_input()
    

I prefer the latter, as it keeps the necessary input logic with the class it belongs to, and note that neither currently has any validation of the input (see e.g. Asking the user for input until they give a valid response).


If you want to have multiple users, you could hold them in a dictionary using a unique key (e.g. their userid - note that Stack Overflow allows multiple users to have the same name, so that wouldn't be unique):

users = {}
for _ in range(10):  # create 10 users
    user = StackOverflowUser.from_input()  # from user input
    users[user.userid] = user  # and store them in the dictionary

Then each user is accessible as users[id_of_user]. You could add a check to reject users with duplicate IDs as follows:

if user.userid in users:
    raise ValueError('duplicate ID')
Community
  • 1
  • 1
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • I'm trying to do this `return cls(...) if flag == 1 else cls(...)` , "..." are different inputs, the `if-else` aren't working in `from_input()` function return stmts. control simply jumps to `else` part. Do you know why? – Anu Nov 06 '19 at 00:18
  • @anu how could I possibly guess? Presumably `flag != 1`, but I don't know where that value is coming from. – jonrsharpe Nov 06 '19 at 07:20
  • here, is the code snippet! `@classmethod def from_input(cls): flag = input("Press 1 || 2 \n") print(flag) return cls( input('Name: '), int(input('User ID: ')), int(input('Reputation: '))) if flag ==1 else cls( input('Name1: '), int(input('User ID1: ')), int(input('Reputation1: ')))`, I am taking flag as another input in the `from_input ()`, it is like, if user press 1 do this and if user press 2 do that. – Anu Nov 06 '19 at 20:05
4

Take input and store them in variables and use them to create the instance

 class StackOverflowUser:
        def __init__(self, name, userid, rep): 
            self.name = name
            self.userid = userid
            self.rep = rep

 name = raw_input("Enter name: ")
 userid = int(raw_input("Enter user id: "))
 rep = int(raw_input("Enter rep: "))

 dave = StackOverflowUser(name, userid, rep)
Anvesh Arrabochu
  • 165
  • 1
  • 2
  • 11
  • 1
    @silentphoenix how is this **not** the user creating an instance themselves? What are you *actually trying to achieve?!* – jonrsharpe Sep 22 '15 at 16:12
  • @silentphoenix But we cannot answer questions that we don't understand, which makes this a waste of everyone's time. It's still not clear what difference you see between *"the instance, not just the attributes"* - the attributes **define** the instance. Try to articulate clearly what you're asking, e.g. by providing examples of how you would use the functionality once you'd implemented it. – jonrsharpe Sep 22 '15 at 16:15
  • 1
    @silentphoenix 1. To create the instance from command line `from user.py import StackOverflowUser` `user = StackOverflowUser(name_here, userid_here, rep_here)` Is this what you wanted? – Anvesh Arrabochu Sep 22 '15 at 16:17
  • 2
    @silentphoenix: If you want multiple instances then put them in a list or a dictionary. – Matthias Sep 22 '15 at 16:18
  • 2
    _"what if the user is not named dave?"_. Then the code will still work. You could change your variable name to `user` or `foo` or `___` and it should still operate the same way. The variable name should not contain the name of the user; that is what the `name` attribute is for. – Kevin Sep 22 '15 at 16:20