我正在尝试将我的代码编译成Python 3模块。我在IDLE中选择“运行模块”时运行正常,但在尝试创建分发时收到以下语法错误:
File "/usr/local/lib/python3.2/dist-packages/simpletriple.py", line 9
def add(self, (sub, pred, obj)):
^
SyntaxError: invalid syntax
任何人都可以帮助指出语法有什么问题吗?这是完整的代码:
import csv
class SimpleGraph:
def __init__(self):
self._spo = {}
self._pos = {}
self._osp = {}
def add(self, (sub, pred, obj)):
"""
Adds a triple to the graph.
"""
self._addToIndex(self._spo, sub, pred, obj)
self._addToIndex(self._pos, pred, obj, sub)
self._addToIndex(self._osp, obj, sub, pred)
def _addToIndex(self, index, a, b, c):
"""
Adds a triple to a specified index.
"""
if a not in index: index[a] = {b:set([c])}
else:
if b not in index[a]: index[a][b] = set([c])
else: index[a][b].add(c)
def remove(self, (sub, pred, obj)):
"""
Remove a triple pattern from the graph.
"""
triples = list(self.triples((sub, pred, obj)))
for (delSub, delPred, delObj) in triples:
self._removeFromIndex(self._spo, delSub, delPred, delObj)
self._removeFromIndex(self._pos, delPred, delObj, delSub)
self._removeFromIndex(self._osp, delObj, delSub, delPred)
def _removeFromIndex(self, index, a, b, c):
"""
Removes a triple from an index and clears up empty indermediate structures.
"""
try:
bs = index[a]
cset = bs[b]
cset.remove(c)
if len(cset) == 0: del bs[b]
if len(bs) == 0: del index[a]
# KeyErrors occur if a term was missing, which means that it wasn't a valid delete:
except KeyError:
pass
def triples(self, (sub, pred, obj)):
"""
Generator over the triple store.
Returns triples that match the given triple pattern.
"""
# check which terms are present in order to use the correct index:
try:
if sub != None:
if pred != None:
# sub pred obj
if obj != None:
if obj in self._spo[sub][pred]: yield (sub, pred, obj)
# sub pred None
else:
for retObj in self._spo[sub][pred]: yield (sub, pred, retObj)
else:
# sub None obj
if obj != None:
for retPred in self._osp[obj][sub]: yield (sub, retPred, obj)
# sub None None
else:
for retPred, objSet in self._spo[sub].items():
for retObj in objSet:
yield (sub, retPred, retObj)
else:
if pred != None:
# None pred obj
if obj != None:
for retSub in self._pos[pred][obj]:
yield (retSub, pred, obj)
# None pred None
else:
for retObj, subSet in self._pos[pred].items():
for retSub in subSet:
yield (retSub, pred, retObj)
else:
# None None obj
if obj != None:
for retSub, predSet in self._osp[obj].items():
for retPred in predSet:
yield (retSub, retPred, obj)
# None None None
else:
for retSub, predSet in self._spo.items():
for retPred, objSet in predSet.items():
for retObj in objSet:
yield (retSub, retPred, retObj)
# KeyErrors occur if a query term wasn't in the index, so we yield nothing:
except KeyError:
pass
def value(self, sub=None, pred=None, obj=None):
for retSub, retPred, retObj in self.triples((sub, pred, obj)):
if sub is None: return retSub
if pred is None: return retPred
if obj is None: return retObj
break
return None
def load(self, filename):
f = open(filename, "rb")
reader = csv.reader(f)
for sub, pred, obj in reader:
sub = unicode(sub, "UTF-8")
pred = unicode(pred, "UTF-8")
obj = unicode(obj, "UTF-8")
self.add((sub, pred, obj))
f.close()
def save(self, filename):
f = open(filename, "wb")
writer = csv.writer(f)
for sub, pred, obj in self.triples((None, None, None)):
writer.writerow([sub.encode("UTF-8"), pred.encode("UTF-8"), obj.encode("UTF-8")])
f.close()
if __name__ == "__main__":
g = SimpleGraph()
g.add(("blade_runner", "name", "Blade Runner"))
g.add(("blade_runner", "name", "Blade Runner"))
g.add(("blade_runner", "release_date", "June 25, 1982"))
g.add(("blade_runner", "directed_by", "Ridley Scott"))
print list(g.triples((None, None, None)))
print list(g.triples(("blade_runner", None, None)))
print list(g.triples(("blade_runner", "name", None)))
print list(g.triples(("blade_runner", "name", "Blade Runner")))
print list(g.triples(("blade_runner", None, "Blade Runner")))
print list(g.triples((None, "name", "Blade Runner")))
print list(g.triples((None, None, "Blade Runner")))
print list(g.triples(("foo", "name", "Blade Runner")))
print list(g.triples(("blade_runner", "foo", "Blade Runner")))
print list(g.triples(("blade_runner", "name", "foo")))
答案 0 :(得分:32)
PEP 3113解释了为什么在Python 3中删除了这个功能“tuple参数解包”。它还解释了如何移植使用它们的代码。在这种情况下,您需要更改如下函数:
def add(self, (sub, pred, obj)):
self._addToIndex(self._spo, sub, pred, obj)
self._addToIndex(self._pos, pred, obj, sub)
self._addToIndex(self._osp, obj, sub, pred)
到一个版本,它将元组作为单个参数传递并手动解压缩:
def add(self, sub_pred_obj):
sub, pred, obj = sub_pred_obj
self._addToIndex(self._spo, sub, pred, obj)
self._addToIndex(self._pos, pred, obj, sub)
self._addToIndex(self._osp, obj, sub, pred)
对于lambda
函数,您不能使用赋值来解压缩。最好的解决方案通常是不拆包。例如,更改此:
lambda (x, y): (y, x)
......对此:
lambda xy: (xy[1], xy[0])
对于复杂的函数,这可能会变得很丑陋 - 但是对于复杂的函数,无论如何你可能想要def
。
值得注意的是,通过2to3
,modernize
或futurize
运行代码会在def
和lambda
中发现此问题,并准确建议这些解决方案:
$ echo 'lambda (x,y): (y,x)' | 2to3 -
--- <stdin> (original)
+++ <stdin> (refactored)
@@ -1 +1 @@
-lambda (x,y): (y,x)
+lambda x_y: (x_y[1],x_y[0])
$ echo -e 'def foo((x,y)):\n return (y,x)\n' | 2to3 -
--- <stdin> (original)
+++ <stdin> (refactored)
@@ -1 +1 @@
-def foo((x,y)):
+def foo(xxx_todo_changeme):
+ (x,y) = xxx_todo_changeme
如果你试图将Python 2.x代码移植到3.x(或双版本代码)并且不知道这两种语言,你几乎肯定想要使用这些工具之一 - 或IDE插件包装他们 - 帮助。 (尽管您可能不想按原样使用其输出。)