Bruno Desthuilliers wrote: > Sambo a écrit : > >> By accident I assigned int to a class member 'count' which was >> initialized to (empty) string and had no error till I tried to use it >> as string, obviously. Why was there no error on assignment( near the >> end ). > > > Python is dynamically typed - which means that it's not the name that > holds type info, but the object itself. names are just, well, names... > Hmm.. so I could have one instance with (int)count and (string)count? (yay DBase flashback, BRRR) I was going to initialize the vars in __init__() but somehow it didn't make sense to me( but left couple of them there).
> BTW, I failed to see where you assigned an int to the class attribute > 'count'. I just saw a try to call a string - which should raise a > TypeError. > I must have fixed it before posting. gr_info.count = gr_info.first = gr_info.last = 0 ??? except ValueError: gr_info.count(0) ??? not sure what I was thinking there (maybe I was trying to triple fault the CPU hehe) >> class Cgroup_info: > > > Do yourself (and anyone having to work on or with your code) a favour: > use new-style classes (ie : inherit from 'object'). And FWIW, the > convention for class names is CamelCase - preferably without MS-like > hungarian annotation. > Those damn hungarians with their calculators and notations, only later did it occur to me to paste the "class ServerInfo():" statement above. > this creates a local variable 'group_name', bound to an empty string. > Using the reference to the current instance (usually named 'self', and > always passed in as first param) is *not* optional. > >> count = "0" #last time checked and processed/retrieved In __init__() it was an oversight but after the class className()... I may have thought it unnecessary, otherwise class consists only of a group of functions if as you say any vars should be created/initialized in __init__() hmmm. > the string module is mostly deprecated. Use str object methods instead - > or if you just want to create an int from it's representation as a > string, int(self.count). > Are string object methods among others, things like: words = sentence.split() This no longer works for me is it because I imported 'string' , didn't import something or didn't use "from string import *" instead. ( must be a year since I last played with python.) > >> gr_info.group_name = grp > > > Tthis create a new instance attribute "group_name" on the gr_info > object. This instance attribute will shadow the class attribute of the > same name. > Hmmm . so what is a class attribute good for? > Also, FWIW, if you always know the value for group_name when > instanciating a Cgroup_info object, you might as well pass it to the > initializer. > Good point. >> try: >> ind = self.group_list.index( grp ) > > > The common convention for indices in each and every language is 'i'. If > you really want a meaningful name, then group_index would be better. > lol, well like in a book and increasingly on the net index in used to refer to a list. So... I guess subscribed_group_list_index(_pointer) might be workable. > Also, for this kind of lookups, dicts are really faster than lists. > I am storing group count first last, although I am considering moving the numeric data elsewhere, for about 100 items .. I'll leave dictionaries for future learning. >> return ( gr_info ) > > > parenthesis here are useless (and FWIW, they would be just as useless in > C++). > A habit, true in python , in C, I think I remember reading about return function and statement. I was important at some point in C or perhaps way back in Pascal. >> print ind >> if len( self.group_list[ind].split() ) == 4: >> gr_info.count = self.group_list[ind].split()[1] >> gr_info.first = self.group_list[ind].split()[2] >> gr_info.last = self.group_list[ind].split()[3] > > > group_list[ind] is the same as grp, isn't it ? if so, using grp directly > might be much more efficient *and* much more readable. > no grp is the (string) group name that was used earlier to find the right item in the list. > Also, you're calling 4 times the same method. This is highly > inefficient. Try this instead: > parts = grp.split() > if len(parts) == 4: > gr_info.count, gr_info.first, gr_info.last = parts[1:] > > yes I realized that in another function but forgot about the unpacking assignment of a slice. >> else: >> gr_info.count = gr_info.first = gr_info.last = "0" > > > This style of "chained assignment" can be a real gotcha in Python. In > this case, it is safe since "0" is immutable. But using a mutable object > instead would lead to probably unexpected results. Try this: > > a = b = [] > a.append(1) > print b I rarely do that even in C particularly when working with struct members, but now with shorter names it is affordable. barely remembered reading about it. > > You have to understand that Python "variables" (the correct name is > "bindings") are just the association (in a given namespace) of a name > and a *reference* (kind of a smart pointer) to an object. > >> return( gr_info ) > > > Here's a possible rewrite of your code. It's certainly not how it should > be done, but (apart from going into wild guesses) it's difficult to come > up with anything better without knowing the specs. Anyway, it should > help you grasp a more pythonic way to do things: > > class GroupInfo(object): > > def __init__(self, group_name, count="0", first="0", last=""): > self.group_name = group_name > self.count = count #last time checked and processed/retrieved > self.first = first > self.last = last > > self.retrieval_type = "" # always , ask( if more than some > limit), none > self.date_checked = "" > self.time_checked = "" > self.new_count = "" > self.new_first = "" > self.new_last = "" > > # local storage maintanance vars > self.pointer_file = "" > self.message_file = "" > > #maintanance vars > self.cur_mess_num = 0 > self.cur_mess_id = "" > > # if you want to store count as string > # but retrieve it as an int. The setter will > # be used by the initializer, and will then create > # the implementation attribute _count > def _get_count(self): > return int(self._count) > > def _set_count(self, value): > self._count = str(value) > > count = property(_get_count, _set_count) > > > class ServerInfo(object): > def __init__(self, ???) > self._groups = {} # dict lookup is faster > # ... > def has_group(self, group_name): > return self._groups.has_key(group_name) > > def get_group_stat(self, group_name): > if not self.has_group(group_name): > return GroupInfo(group_name, "0") > > parts = group_name.split() > if len(parts) != 4: > parts = [None, "0", "0", "0"] > return GroupInfo(group_name, *(parts[1:4])) > > > As a last point, I'd second Fredrik : don't try to write C++ in Python. > Learn to write Python instead. The (freely available) "Dive into Python" > book should be a good place to get started. > > HTH New class style eh, I haven't got a grasp of the old style and exceptions only out of necessity. Either the Python exception docs were easier to understand or simply since I had to, to use those Inet classes , I finally broke down. I may have to go to C with this, for the GUI and I don't think building list of 100,000 messages is realistic . Well Thank You for all the good pointers. -- http://mail.python.org/mailman/listinfo/python-list