Python 编辑:名称空间和异常处理

Python 编辑:名称空间和异常处理,python,Python,在我的《计算机科学导论》课上,我们正在学习名称空间。我理解这个概念,就像导入一个模块,比如math,然后我们导入一个名称空间和名称空间下的类属性,但是执行这个过程对我来说非常混乱。以下是我不知道如何开始执行的问题之一: 编写一个函数,name\u add(a,b),它使用异常处理(只是一个简单的try/except语句)来添加两个对象a和b,并返回结果。如果用户使用未定义+运算符的任何类型调用函数,函数应打印一条消息,说明加法运算符在类型(a)和类型(b)之间未定义(无论这些类型是什么)…..l

在我的《计算机科学导论》课上,我们正在学习名称空间。我理解这个概念,就像导入一个模块,比如math,然后我们导入一个名称空间和名称空间下的类属性,但是执行这个过程对我来说非常混乱。以下是我不知道如何开始执行的问题之一:

编写一个函数,
name\u add(a,b)
,它使用异常处理(只是一个简单的
try/except
语句)来添加两个对象a和b,并返回结果。如果用户使用未定义
+运算符的任何类型调用函数,函数应打印一条消息,说明加法运算符在
类型(a)
类型(b)
之间未定义(无论这些类型是什么)…..l

如果有人能一步一步地解释这个函数应该是什么样子,或者他们用初学者的术语问什么,我会非常感激,因为我根本不理解这个函数,或者它与名称空间的关系

>>> foo = 1
>>> 
>>> def bar():
...     global foo
...     foo = 2
... 
>>> bar()
>>> foo
2
如果不想修改全局变量,只需使用:

# Inside yourfuncs.py
def adder(a, b):
    """
    Returns the sum of a and b, or raises an exception.
    """
    try:
        return a + b
    except TypeError:
        print 'Oops'
        raise
然后:


请注意,我没有阻止错误传播。当它工作时不要返回总和,当它不工作时不要返回错误字符串。那是个糟糕的设计。如果您想引发自己的异常,这是一个好主意。

要修改在函数外部声明的变量,您必须在函数中使用
global
关键字:

a = 1
def mod(b):
    global a
    a = b

mod(2)
print a
#prints 2
def main(argv):
    """Main program for the nc2pdf utility.

    :argv: command line arguments
    """
    if len(argv) == 1: # No filenames given, only the name of the script
        binary = os.path.basename(argv[0])
        print __proginfo__
        print "Usage: {} [file ...]".format(binary)
        print
        sys.exit(0)
    del argv[0]
    for fn in argv: # Loop over all the files
        try:
            ofn = outname(fn) # outname can raise ValueError...
            with open(fn, 'r') as inf: # Open can raise IOError
                rd = inf.read()
        except ValueError:
            fns = "Cannot construct output filename. Skipping file '{}'."
            print fns.format(fn)
            continue
        except IOError:
            print "Cannot open the file '{}'. Skipping it.".format(fn)
            continue
        ... # do something with the file's data
注意:这适用于不可变类型(字符串、数字、布尔值、元组),但适用于列表:

a = [1,2]
def mod(b):
    a[0] = b

mod(2)
print a
#prints [2,2]

对于您在问题正文中提到的问题(与标题完全不同),我建议您使用Ronald Smith的答案。

您需要捕获TypeError异常。以下是问题的答案:

def name_add(a,b):
    try:
        return a+b
    except TypeError:
        print 'The + operator is not defined for a and b'
        return None
正如Lattyware所评论的,捕获异常并仅仅打印消息不是一种好的做法。你应该:

  • 解决函数中的异常,使函数能够继续并产生合理的结果(在这种情况下不可能)
  • 让程序在更高级别捕获异常
看看我的一个程序的片段。这是顶级功能:

a = 1
def mod(b):
    global a
    a = b

mod(2)
print a
#prints 2
def main(argv):
    """Main program for the nc2pdf utility.

    :argv: command line arguments
    """
    if len(argv) == 1: # No filenames given, only the name of the script
        binary = os.path.basename(argv[0])
        print __proginfo__
        print "Usage: {} [file ...]".format(binary)
        print
        sys.exit(0)
    del argv[0]
    for fn in argv: # Loop over all the files
        try:
            ofn = outname(fn) # outname can raise ValueError...
            with open(fn, 'r') as inf: # Open can raise IOError
                rd = inf.read()
        except ValueError:
            fns = "Cannot construct output filename. Skipping file '{}'."
            print fns.format(fn)
            continue
        except IOError:
            print "Cannot open the file '{}'. Skipping it.".format(fn)
            continue
        ... # do something with the file's data

在这种情况下,可以通过跳过(而不是处理)命令行上命名的其中一个文件并转到下一个文件来处理异常。在这里不处理异常会使程序崩溃,即使其他文件可能仍在处理中。文件名可能拼写错误,或者进程可能没有访问该文件的权限。这些事情都会发生,应该优雅地处理。

我看不到与名称空间的关系,这似乎很简单。我不知道Python有“名称空间”。@squiguy Python中的所有东西都在某种名称空间中。@squiguy:启动Python解释器并键入
导入此
。看最后一行…@squiguy,我认为发问者指的是更一般意义上的名称空间,比如可以从给定范围访问的名称集。我认为他指的是返回值,而不是修改全局答案,但是是的,问题的主体是一个完全不同的故事。我认为他谈论的是返回值,而不是修改global@cmd-标题说,
一个Python函数,它修改函数外部定义的变量
@orokusaki是的,但问题接着完全改变了所问的问题,就我所知,@orokusaki不要根据题目来判断一个问题?当某个问题失败时,返回
None
是一个非常糟糕的主意。最好使用
raise
重新引发异常。