On Friday, July 25, 2014 11:25:15 PM UTC-4, Chris Angelico wrote: > On Sat, Jul 26, 2014 at 10:06 AM, Bruce Whealton > Chris, In response to your comments below, I'm comfortable changing this to use python 3. > As others have said, this is something that changed in Python 3. So > you have two parts to the problem: firstly, your code is bound to > Python 2 by a triviality, and secondly, Eclipse is complaining about > it. > > > But a better solution, IMO, would be to avoid that implicit tuple > unpacking. It's not a particularly clear feature, and I'm not sorry > it's gone from Py3. The simplest way to change it is to just move it > into the body: >
OK, that makes sense. So, I cut out the "Alternatively... " suggestion you made. > > > def add(self, args): > > sub, pred, obj = args > > # rest of code as before > > > > Preferably with a better name than 'args'. Yes, I could call it triples. > > > triples = list(self.triples((sub, pred, obj))) > > > > > > Are the two sets parentheses needed after self.triples? That syntax is > > > confusing to me. It seems that it should be > > > triples = list(self.triples(sub, pred, obj)) > > > > No, that's correct. The extra parens force that triple to be a single > > tuple of three items, rather than three separate arguments. Here's a > > simpler example: > > >>> lst = [] > > >>> lst.append(1,2,3) > > Traceback (most recent call last): > > File "<pyshell#25>", line 1, in <module> > > lst.append(1,2,3) > > TypeError: append() takes exactly one argument (3 given) > > >>> lst.append((1,2,3)) > > >>> addme = 4,5,6 > > >>> lst.append(addme) > > >>> lst > > [(1, 2, 3), (4, 5, 6)] > > This is helpful and makes sense... clarifies it for me. > > The list append method wants one argument, and appends that argument > to the list. Syntactically, the comma has multiple meanings; when I > assign 4,5,6 to a single name, it makes a tuple, but in a function > call, it separates args in the list. I don't see why the triples() > function should be given a single argument, though; all it does is > immediately unpack it. It'd be better to just remove the parens and > have separate args: > > triples = list(self.triples(sub, pred, obj)) > I didn't see the above in the code... Is this something I would need to add and if so, where? > > > def triples(self, sub, pred, obj): > > > > While I'm looking at the code, a few other comments. I don't know how > much of this is your code and how much came straight from the book, > but either way, don't take this as criticism, but just as suggestions > for ways to get more out of Python. > So far it is just from the book, and just serves as an example... It is also a few years old, having been published in 2009. > > > Inside remove(), you call a generator (triples() uses yield to return > multiple values), then construct a list, and then iterate exactly once > over that list. Much more efficient and clean to iterate directly over > what triples() returns, as in save(); that's what generators are good > for. > > > > In triples(), the code is deeply nested and repetitive. I don't know > if there's a way to truly solve that, but I would be inclined to > flatten it out a bit; maybe check for just one presence, to pick your > index, and then merge some of the code that iterates over an index. > Not sure though. > I would have to get a better understanding of this. > > > (Also: It's conventional to use "is not None" rather than "!= None" to > > test for singletons. It's possible for something to be equal to None > > without actually being None.) > > > > I would recommend moving to Python 3, if you can. Among other > benefits, the Py3 csv module allows you to open a text file rather > than opening a binary file and manually encoding/decoding all the > parts separately. Alternatively, if you don't need this to be saving > and loading another program's files, you could simply use a different > file format, which would remove the restrictions (and messes) of the > CSV structure. I was curious about why the binary flag was being used. It just made no sense to me. > > > > Instead of explicitly putting "f.close()" at the end of your load and > save methods, check out the 'with' statement. It'll guarantee that the > file's closed even if you leave early, get an exception, or anything > > like that. Also, I'd tend to use the .decode() and .encode() methods, > rather than the constructors. So here's how I'd write a Py2 load: I would like to see this in python 3 format. > > def load(self, filename): > > with open(filename, "rb") as f: > > for sub, pred, obj in csv.reader(f): > > self.add((sub.decode("UTF-8"), pred.decode("UTF-8"), > > obj.decode("UTF-8"))) > > > > (You might want to break that back out into three more lines, but this > > parallels save(). If you break this one, you probably want to break > > save() too.) > > > > Hope that helps! > > > > ChrisA Thanks, Bruce -- https://mail.python.org/mailman/listinfo/python-list