Prob. Code Downloaded for Programming the Semantic Web (python code)
Bruce Whealton
futurewavewebdevelopment at gmail.com
Mon Jul 28 07:07:27 EDT 2014
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
More information about the Python-list
mailing list