关于python:嵌套参数未编译

Nested arguments not compiling

我正试图将我的代码编译成一个python 3模块。当我在空闲状态下选择"运行模块"时,它运行良好,但当我尝试创建分发时,它会收到以下语法错误:

1
2
3
4
File"/usr/local/lib/python3.2/dist-packages/simpletriple.py", line 9
    def add(self, (sub, pred, obj)):
                  ^
SyntaxError: invalid syntax

有人能帮忙指出语法有什么问题吗?以下是完整的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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")))


PEP 3113解释了为什么这个特性"tuple参数解包"在python 3中被删除。它还解释了如何移植使用它们的代码。在这种情况下,您需要更改如下函数:

1
2
3
4
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)

到将元组作为单个参数传递并手动解包的版本:

1
2
3
4
5
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函数,不能使用赋值进行解包。最好的解决方案通常是不解包。例如,更改此项:

1
lambda (x, y): (y, x)

……

1
lambda xy: (xy[1], xy[0])

对于复杂的函数,这可能会变得很难看,但对于复杂的函数,您可能无论如何都希望使用def它们。

值得注意的是,通过2to3modernizefuturize运行您的代码,在deflambda中都会发现这个问题,并准确地提出这些解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ 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)):
    return (y,x)
'
| 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插件来提供帮助。(尽管您可能不想按原样使用其输出。)