Juan Christian wrote: > On Sun, Sep 7, 2014 at 5:04 AM, Peter Otten <__pete...@web.de> wrote: >> >> It's not a good approach and it's not pythonic. >> >> In Python you should avoid accessor functions and (pseudo-)private >> __attributes ("Python is not Java"). So >> >> class User: >> def __init__(self, id): >> self.id = id >> # load attributes >> self.personname = [personname from JSON] >> ... >> >> user = User(42) >> >> is certainly better. You might also consider making the class less >> dependent >> of the way you acquire the corresponding data: >> >> class User: # in Python 2: class User(object): ... >> def __init__(self, id, personname, ...) >> self.id = id >> self.personname = personname >> ... >> @classmethod >> def from_id(class_, id): >> # load attributes >> return User(id, personname, ...) >> >> jeff = User(42, "Jeff", ...) >> jack = User.from_id(43) > > > > Ok, no pseudo-private attributes. I read it in tutorials from 2013 and in > the course that I'm taking that this would be a good pythonic way to deal > with class attributes. They wouldn't be truly private, but someone using > the program would see the " __ " in the beginning of the attribute and > wouldn't call it directly, "because we are all adults and such", you > saying that this approach doesn't exist in real life?
The double underscore plus name mangling is mainly to avoid name collisions in subclasses; to signal "this is private" a single underscore would suffice. But you then go on to make the attribute public via a a getter. In that case my first choice are normal attributes so that you can write print(user.personname) # pythonic instead of print(user.get_personname()) # Javaism If you want to prohibit the user from doing user.personname = "Frankenstein" because the new name is not propagated to the database and the assignment puts your application into an inconsistent state which you want to avoid by some "bondage and discipline" you can change personname into a property: class User: def __init__(self, id): ... self._personname = [as extracted from the JSON] @property def personname(self): return self._personname user = User(42) print(user.personname) # implicitly calls the personname(self) method > I can't give all the 8 attributes to '__init__' because I don't even have > them. At least not now ;) My suggestion would decouple creation of the User instance and fetching of user-related data from a server. > I would call it with ID only and them the API server would return me > all the info, and then I would set them. I didn't learn '@classmethod' > decoration yet, but I presume it would work as a 'get()', right? The thing > is, where 'user with id 43' is stored? You get it using 'from_id' but we > don't have any list in there the store users, I got confused in that part. Maybe it becomes clearer with a small change. Instead of the classmethod you could use a normal function: class User: def __init__(self, id, personname, ...): self.id = id self.personname = personname ... def fetch_user_from_server(id): json_user = fetch data_from_server(id) return User(id, json_user["personname"], ...) jim = fetch_user_from_server(42) If you should later decide that you want to provide a way to allow entering new users you could use the User class for that, too: def create_new_user(): personname = input("Name: ") # in real code this would rather be a # gui dialog or web page ... return User(None, personname, ...) new_guy = create_new_user() save_user_to_server(new_guy) You don't have to worry that the __init__() method tries to load data for an inexistent user. But even if you are sure you'll never do that it is still a good idea to keep concerns separate, if only to write independent unit tests for the User class and the server access. _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor