为什么我的函数没有定义?

时间:2016-11-07 04:53:44

标签: python class

import re, traceback, keyword

def pnamedtuple(type_name, field_names, mutable=False):
    def show_listing(s):
        for i, l in enumerate(s.split('\n'), 1):
            print('{num: >4} {txt}'.format(num= i, txt= l.rstrip()))


    class type_name:
        def __init__(self, x, y):
            self.x = x
            self.y = y
            self._fields = [x,y]
            self._mutable = False

        def __repr__(self):
            return 'Point(x={x},y={y})'.format(x=self.x,y=self.y)

        def get_x(self):
            return self.x

        def get_y(self):
            return self.y

        def __getitem__(self, i):
            if i == 0:
                i = "x"
            elif i == 1:
                i = "y"

            if i == "x":
                return self.get_x()
            elif i == "y":
                return self.get_y()
            else:
                raise IndexError("Invalid key: {}".format(i))

        def __eq__(self,right):
            if self[1] == right[1]:
                return True
            return False

        def _replace(self,**kargs ):
            for key, value in kargs.iteritems():
                z = zip(key,value)
            for x in z:
                for y in self.field:
                    if x[0] == y:
                        self.x = x[1]
                    if x[0] == y:
                        self.y = x[1]

    name_space = dict(__name__='pnamedtuple_{type_name}'.format(type_name= type_name))
    try:
        exec(class_definition,name_space)
        name_space[type_name].source_code = class_definition
    except(SyntaxError, TypeError):
        show_listing(class_definition)
        traceback.print_exc()
    return name_space[type_name]

标题是def pnamedtuple(type_name,field_names,mutable = False):对此函数的示例调用是

Point = pnamedtuple('Point', ['x','y'], mutable=False)

,相当于写作

Point = pnamedtuple('Point', 'x y') 
Point = pnamedtuple('Point', 'x,y')

类型和字段的合法名称必须以字母开头,后面可以跟0个或更多字母,数字或下划线字符

field_names必须是合法名称列表,例如[' x',' y']或' x y'或' x ,y'

p =点(1,2)写p.get_x()或p [0]),或p [' x']返回1的结果

new_origin = origin._replace(y = 5),然后print(origin,new_origin)将显示为Point(x = 0,y = 0)Point(x = 0,y = 5)

然而,当我运行此函数时,它表明一切都没有定义。 我在下面添加了bsc.txt代码,它有点长:

 6 # Test pnamedtuple (as pnt)
 7 *Error: Triple1    = pnt('Triple1', 'a b c') raised exception NameError: name 'class_definition' is not defined
 8 *Error: print(Triple1.source_code) raised exception NameError: name 'Triple1' is not defined
 9 *Error: Triple2    = pnt('Triple2', 'a,  b,    c') raised exception NameError: name 'class_definition' is not defined
10 *Error: Triple3    = pnt('Triple3', ['a','b','c']) raised exception NameError: name 'class_definition' is not defined
11 *Error: Triple_Bad = pnt(1, 'a b c') raised wrong exception(NameError) should be from list: SyntaxError
12 *Error: Triple_Bad = pnt('Triple_Bad', {'a','b','c'}) raised wrong exception(NameError) should be from list: SyntaxError
13 *Error: Triple_Bad = pnt('3', 'a b c') raised wrong exception(NameError) should be from list: SyntaxError
14 *Error: Triple_Bad = pnt('Triple_Bad', 'a 3 c') raised wrong exception(NameError) should be from list: SyntaxError
15 *Error: Triple_Bad = pnt('Triple_Bad', 'a b if') raised wrong exception(NameError) should be from list: SyntaxError
16 *Error: Triple_Bad = pnt('Triple_Bad', '_a _b _c') raised wrong exception(NameError) should be from list: SyntaxError
17 *Error: Triple_OK  = pnt('Triple_OK', 'a17 b__1 c__2') raised exception NameError: name 'class_definition' is not defined
18 # Test init/repr
19 *Error: t1 = Triple1(1,2,3) raised exception NameError: name 'Triple1' is not defined
20 *Error: repr(t1) raised exception NameError: name 't1' is not defined
21 *Error: t2 = Triple2(1,2,3) raised exception NameError: name 'Triple2' is not defined
22 *Error: repr(t2) raised exception NameError: name 't2' is not defined
23 *Error: t3 = Triple3(1,2,3) raised exception NameError: name 'Triple3' is not defined
24 *Error: repr(t3) raised exception NameError: name 't3' is not defined
25 *Error: t3 = Triple3(c=3,b=2,a=1) raised exception NameError: name 'Triple3' is not defined
26 *Error: repr(t3) raised exception NameError: name 't3' is not defined
27 *Error: tok= Triple_OK(c__2=3,b__1=2,a17=1) raised exception NameError: name 'Triple_OK' is not defined
28 *Error: repr(tok) raised exception NameError: name 'tok' is not defined
29 *Error: t1.a raised exception NameError: name 't1' is not defined
30 *Error: t1.b raised exception NameError: name 't1' is not defined
31 *Error: t1.c raised exception NameError: name 't1' is not defined
32 *Error: t1.d raised wrong exception(NameError) should be from list: AttributeError
33 # Test get_ methods
34 *Error: t1.get_a() raised exception NameError: name 't1' is not defined
35 *Error: t1.get_b() raised exception NameError: name 't1' is not defined
36 *Error: t1.get_c() raised exception NameError: name 't1' is not defined
37 *Error: t1.get_d() raised wrong exception(NameError) should be from list: AttributeError
38 *Error: l = [Triple1(a=1,b=2,c=3),Triple1(b=1,c=2,a=3),Triple1(c=1,a=2,b=3)] raised exception NameError: name 'Triple1' is not defined
39 *Error: l.sort(key=Triple1.get_a) raised exception NameError: name 'l' is not defined
40 *Error: l raised exception NameError: name 'l' is not defined
41 # Test __getitem__ functions
42 *Error: t1[0] raised exception NameError: name 't1' is not defined
43 *Error: t1[1] raised exception NameError: name 't1' is not defined
44 *Error: t1[2] raised exception NameError: name 't1' is not defined
45 *Error: t1['a'] raised exception NameError: name 't1' is not defined
46 *Error: t1['b'] raised exception NameError: name 't1' is not defined
47 *Error: t1['c'] raised exception NameError: name 't1' is not defined
48 *Error: t1[4] raised wrong exception(NameError) should be from list: IndexError
49 *Error: t1['d'] raised wrong exception(NameError) should be from list: IndexError
50 *Error: t1[3.2] raised wrong exception(NameError) should be from list: IndexError
51 # Test ==
52 *Error: t1 == t1 raised exception NameError: name 't1' is not defined
53 *Error: t1 == t2 raised exception NameError: name 't1' is not defined
54 *Error: t1 == Triple1(a=1,b=2,c=3) raised exception NameError: name 't1' is not defined
55 *Error: t1 == Triple1(a=1,b=1,c=3) raised exception NameError: name 't1' is not defined
56 # Test replace (not mutable)
57 *Error: t1._replace(a=2) raised exception; unevaluated: Triple1(2,2,3)
58 *Error: t1._replace(a=2,c=2) raised exception; unevaluated: Triple1(2,2,2)
59 *Error: t1._replace(a=2,c=2,d=2) raised wrong exception(NameError) should be from list: TypeError
60 *Error: t1 raised exception; unevaluated: Triple1(a=1,b=2,c=3)
61 # Test _replace (mutable)
62 *Error: Triple1 = pnt('Triple1', 'a b c',mutable=True) raised exception NameError: name 'class_definition' is not defined
63 *Error: t1 = Triple1(1,2,3) raised exception NameError: name 'Triple1' is not defined
64 *Error: t1._replace(a=2,c=2) raised exception NameError: name 't1' is not defined
65 *Error: t1 raised exception; unevaluated: Triple1(a=2,b=2,c=2)
66 # Test Extra Credit (prohibit mutation if immutable)
67 *Error: Triple1 = pnt('Triple1', 'a b c',mutable=False) raised exception NameError: name 'class_definition' is not defined
68 *Error: t1 = Triple1(1,2,3) raised exception NameError: name 'Triple1' is not defined
69 *Error: t1.a = 2 raised wrong exception(NameError) should be from list: AttributeError
70 *Error: Triple1 = pnt('Triple1', 'a b c',mutable=True) raised exception NameError: name 'class_definition' is not defined
71 *Error: t1 = Triple1(1,2,3) raised exception NameError: name 'Triple1' is not defined
72 *Error: t1.a = 2 raised exception NameError: name 't1' is not defined
73 *Error: t1 raised exception; unevaluated: Triple1(2,2,3)

可以告诉我为什么我会收到所有这些错误?是因为我的typename有问题吗?有人能告诉我如何解决它吗?非常感谢。

这是我提供的基本代码:

import re, traceback, keyword

def pnamedtuple(type_name, field_names, mutable=False):
    def show_listing(s):
        for i, l in enumerate(s.split('\n'), 1):
            print('{num: >4} {txt}'.format(num= i, txt= l.rstrip()))

# put your code here
# bind class_definition (used below) to the string constructed for the class


# For initial debugging, always show the source code of the class
#show_listing(class_definition)

# Execute the class_definition string in a local namespace, binding the
#   name source_code in its dictionary to the class_defintion; return the
#   class object created; if there is a syntax error, list the class and
#   also show the error
    name_space = dict(__name__='pnamedtuple_{type_name}'.format(type_name= type_name))
    try:
        exec(class_definition,name_space)
        name_space[type_name].source_code = class_definition
    except(SyntaxError, TypeError):
        show_listing(class_definition)
        traceback.print_exc()
    return name_space[type_name]

1 个答案:

答案 0 :(得分:0)

我不确定你的课程定义是什么,或者你从哪里得到它,如果你发布它会非常有用。我想你有一些源代码,并且应该将它包装在一个继承自函数中的基类的类中。

我调用了基类irrelevant,因为名称字面上并不重要,它只会在函数范围内解析,这是评论员所说的。对于你的情况,它不能在外部范围内解决,这不仅是可以接受的,而且是有意的。

这段代码将按照您的预期执行,我想:

import re, traceback, keyword


def pnamedtuple(type_name, field_names, mutable=False):
    def show_listing(s):
        for i, l in enumerate(s.split('\n'), 1):
            print('{num: >4} {txt}'.format(num= i, txt= l.rstrip()))


    class irrelevant:
        def __init__(self, x, y):
            self.x = x
            self.y = y
            self._fields = [x,y]
            self._mutable = False

        def __repr__(self):
            return 'Point(x={x},y={y})'.format(x=self.x,y=self.y)

        def get_x(self):
            return self.x

        def get_y(self):
            return self.y

        def __getitem__(self, i):
            if i == 0:
                i = "x"
            elif i == 1:
                i = "y"

            if i == "x":
                return self.get_x()
            elif i == "y":
                return self.get_y()
            else:
                raise IndexError("Invalid key: {}".format(i))

        def __eq__(self,right):
            if self[1] == right[1]:
                return True
            return False

        def _replace(self,**kargs ):
            for key, value in kargs.iteritems():
                z = zip(key,value)
            for x in z:
                for y in self.field:
                    if x[0] == y:
                        self.x = x[1]
                    if x[0] == y:
                        self.y = x[1]

    name_space = dict(__name__='pnamedtuple_{type_name}'.format(type_name= type_name),irrelevant=irrelevant)
    class_definition = "class Point(irrelevant):\n    pass"

    try:
        exec(class_definition,name_space)
        name_space[type_name].source_code = class_definition
    except(SyntaxError, TypeError):
        show_listing(class_definition)
        traceback.print_exc()
    return name_space[type_name]

Point = pnamedtuple('Point', ['x','y'], mutable=False)
p = Point(1,2)
print(p.get_x())

诀窍是在你的上下文中传递基类时执行你的代码。根据{{​​1}}的初始内容,代码可能需要更改。

很棒的问题,你在哪里获得这项任务?