찾다
백엔드 개발파이썬 튜토리얼异常(exception)和执行失败有什么区别?

例如一个User Class 的 add 方法,在成功的情况下返回用户对象实例,在失败的情况返回False并可以通过getError方法获取失败原因字符串........

说到这里,我好像明白了,难道add方法总是应该返回用户对象,否则抛出异常吗?
但是这样的话,他们的代码量没什么区别的啊。问题在于即使调用add方法处没有捕捉异常,该异常也能进一步向上抛出直至被处理或引发进程崩溃?可是说到底,这和程序自然崩溃有什么区别呢?

---- 以上为自言自语,下面是问题 ----

抛出异常和返回false的区别是什么,两者在什么场景下使用?

回复内容:

首先,这是一个好问题。深入理解二者的区别是突破中等程度程序员的标志之一。

先澄清一个误区,那就是异常非常慢。异常的实现需要保存异常抛出点到异常捕获点的必要信息,这是人们诟病异常性能的主要依据。但是这是错误的。第一,手工按照返回错误的风格取得行为等价于异常的实现性能绝大多数时候比不上语言内置的异常的性能。对于支持原生异常的OS,如Windows,这个差距尤其明显;第二,对于非基于栈的调用实现,异常和返回错误性能几无差别,只是风格不同而已。

回到问题,异常和返回错误的本质区别是什么?答:异常是强类型的,类型安全的分支处理技术;而返回错误是其弱化的,不安全的版本。

先看返回错误的特征。一般来说,需要用特别返回值来标识错误,意味着需要重载特定值得含义。假设一个操作会返回一个int型值,因为其不可能返回负数(如求绝对值),我们一般可以使用-1来作为操作失败(如函数库调用加载错误)的指示。-1在int类型中并无特别含义,然而我们这里强制施加了语义,而这种语义是弱的。没办法通过类型系统检查来确保正确性。

一个增强的办法是同时返回两种值。有的语言内置支持,没有内置支持的可以通过定义一个含有分别表征正确返回类型和错误类型的结构来模拟。这样的好处是传递信息的通道被分离了。

无论如何返回错误,它存在着一个显著的缺点:调用方必须显式检查错误值。当错误发生,必须终止当前操作,返回错误的时候,一般需要定义全新的错误类型。这导致操作不可任意简单组合,如模块B调用模块A发生错误的时候需要返回B定义的错误,而模块C调用A错误时则需要返回C定义的错误,而这两类错误往往是不兼容的。组合相关代码必须加入大量的粘连代码,这导致了代码膨胀,而且非常容易出错。对于接口定义明确的系统,一般定义一套通用的错误码来简化其复杂性。OS内核就是一个例子,它提供了一个适配所有OS调用的错误码表。然而其内部使用的错误码要多得多,并且往往在接口把内部错误码映射到外部错误码。

异常是一种安全的分支处理技术。因为它和错误处理密切相关,人们容易直接把异常看成是错误处理,连名字“异常”都带着浓浓的错误的含义。但是这是一个误解。异常的理论基础是假设某些分支处理中,一个分支和其它分支比起来发生的非常不频繁。与其平等地针对常见和极其罕见的情形进行处理(想一下,正常处理代码和错误处理代码往往一样多,大部分情况下后者其实更多),不如仅仅处理正常的情形,把不常见的情形归于一处统一处理。这样我们书写代码的时候仅仅关注正常情形就可以了。发生错误的时候,特别的流程会帮助程序员直接回到定义了错误处理的地方。

这样说有点过分简化。一般情况下,不能直接跳回。因为在异常抛出点到异常处理点之间,可能存在处于非一致状态的值,等待释放的资源等。所以一般情况下,特殊流程要回溯调用栈,确保执行的事务性。但是仅仅这个特殊流程是不够的,必须有合适的配套代码才行。这导致了额外的复杂性。C++引入的RAII概念是一个创举,然而依然没能全部消除程序员的工作。

因为异常是一个具体的类型,一个函数的signature就不仅仅是输入参数列表,输出参数加函数名,还要包含可能抛出异常列表。因为各个模块定义的异常层次结构迥异,这导致了额外的组合困难。然而和返回错误值的组合困难不同,前者导致的是编译时类型错误,后者则是运行时错误。一般来看,错误暴露的越早越好,我们倾向于前者。

理想情况下,一个异常结构完备的系统不会有运行时错误(大概如此,不展开)。然而因为上面提到的原因,在现有的异常支持的情况下,代码同样复杂,冗余,难以维护。

上面就是异常和错误的基本区别。

第二部分预告:有解决上述问题的优雅方法吗?

我的观点是有。但是因为现有能力还不到不借助任何参考直接澄清此问题,我回留待仔细斟酌,沐浴焚香,换到非手机输入的情况下给出,尽请期待。 都是错误处理的策略,OO语言更倾向异常,相比较判断一个函数可能的错误状况来说,“抛出”状态完整的异常对象被认为是更好的封装 ;你说的情况下,错误即false是最简单的情况,这种情况下,异常未必有优势;一般认为用异常可以简化复杂的错误处理代码,并且只要程序不需要终止执行,try catch比if else的代码更可读(错误处理的策略明显,状态可以更丰富,虽然这不是绝对的)。

result = func();
if (result === ERR_NO_1) {
  ... 
} else if (result === ERR_NO_2) {
  
} else {
  ...
}
一个很简单的例子,你要解析json的请求回包,只返回false的代码可能是
<span class="k">if</span><span class="p">(</span><span class="n">jsonObj</span><span class="p">.</span><span class="n">has</span><span class="p">(</span><span class="s">"xxx"</span><span class="p">))</span>
<span class="p">{</span>
    <span class="k">if</span><span class="p">(</span><span class="n">jsonObj</span><span class="p">.</span><span class="n">has</span><span class="p">(</span><span class="s">"xxxxx"</span><span class="p">))</span>
    <span class="p">{</span>
        <span class="c1">//......... </span>
        <span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span>

<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
写了一些,但是觉得没什么好说的。很多疑惑的问题,见得多了写得多了自然就知道。很多时候没有孰优孰劣,只有风格上的统一。例如C++这样的支持exception的语言,在很多代码库里是完全exception free,而用类C的形式来处理异常。

异常有两类,一类是『我知道这个地方可能出错,调用方必须明确知道出错的风险』,另一类是『这就是个错误,没啥挽救余地了崩溃拉倒』。这两类异常放Java里就是checked exception和unchecked exception的区别。

异常并不仅限于错误处理,很多时候是用来分开处理normal scenario和edge case的。比如说读取一个文件,把文件中每个词出现次数统计一下。这里用Python语法:

<span class="n">word_count</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="k">for</span> <span class="n">word</span> <span class="ow">in</span> <span class="n">words</span><span class="p">:</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">word_count</span><span class="p">[</span><span class="n">word</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
        <span class="n">word_count</span><span class="p">[</span><span class="n">word</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
抛出异常的函数,就不需要返回bool。
设计成返回bool或指针的函数,就不需要异常。

也就是说异常和返回值是永远不同时存在的(当然这是我个人的理解)。

(我觉得,你问题中的add函数如果有可能失败,那么就不抛异常,如果正常情况下不应该失败,那么可以抛异常。但并不一定需要在每一个add函数的地方都加try。加不加得看你的程序逻辑能否以及应该恢复..(这时你也可以写一个辅助函数在其内部调用try add..其他地方使用这个辅助函数:),继续跑。否则就在程序入口加个try,然后退出即可)

好像还没答全你的这个好问题,明天电脑上再讨论讨论。 能返回Either或者Maybe就方便了, 像Either这样错误信息够丰富的情况下根本不需要异常 从WINDOWS实现上来讲一个分支语句,一个是SEH或者全局回调处理,后者可以很好的防止不再预料的情况时程序奔溃! 第一,异常都是可以预见的,所以它有可预知性。第二,异常不关心发生的条件而关心如何善后。第三,异常是被定义过的错误,比较容易定位问题。第四,异常可以传递。

执行失败的结果就是直接退出。。。。 假设你对某个异常(或者说执行错误)需要这样处理:
——在用户界面显示一条错误信息。

但是这个异常是由底层的API,比如数据库调用抛出的,而客户端没有直接调用这个API的权限。
这时候,你可以选择:
  1. 抛出异常,一层一层抛出
  2. 定义错误代码,一层一层返回
你选2,
  1. 发现每一个函数都增加了一个叫err的传入参数,这个参数并没有什么卵用,因为它会被不加处理地返回给上一层,直达UI。
  2. 这并没有什么问题,但是有一天你被告知某个底层改动导致这个API会抛出一种新的错误,老板要求你对这种错误在调用栈里的某一层处理掉。于是你增加了对异常类型的判断。
  3. 后来,另一个新的模块需要复用你在上次处理的那个module里写的异常信息,你为了不c&p代码,把异常信息封装成了一个Error类,每个从Error继承来的子类都保存着自己独有的异常信息。
  4. 你对自己造的轮子很满意,然后用到了现在维护的模块中——现在你的代码看起来是这样:
    def f(err, **kwargs):
       result = None
       if(err.code == 1):
          handle_this_err(err)
       elif(err.code == 2):
          return (err, result)
       else:
          result = handle_data(**kwargs)
       return (None, result)
    
    跨函数error code。 强制错误检查。 happen path 简化。 最后一个,你得会写异常安全的代码。
성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
Python 학습 : 2 시간의 일일 연구가 충분합니까?Python 학습 : 2 시간의 일일 연구가 충분합니까?Apr 18, 2025 am 12:22 AM

하루에 2 시간 동안 파이썬을 배우는 것으로 충분합니까? 목표와 학습 방법에 따라 다릅니다. 1) 명확한 학습 계획을 개발, 2) 적절한 학습 자원 및 방법을 선택하고 3) 실습 연습 및 검토 및 통합 연습 및 검토 및 통합,이 기간 동안 Python의 기본 지식과 고급 기능을 점차적으로 마스터 할 수 있습니다.

웹 개발을위한 파이썬 : 주요 응용 프로그램웹 개발을위한 파이썬 : 주요 응용 프로그램Apr 18, 2025 am 12:20 AM

웹 개발에서 Python의 주요 응용 프로그램에는 Django 및 Flask 프레임 워크 사용, API 개발, 데이터 분석 및 시각화, 머신 러닝 및 AI 및 성능 최적화가 포함됩니다. 1. Django 및 Flask 프레임 워크 : Django는 복잡한 응용 분야의 빠른 개발에 적합하며 플라스크는 소형 또는 고도로 맞춤형 프로젝트에 적합합니다. 2. API 개발 : Flask 또는 DjangorestFramework를 사용하여 RESTFULAPI를 구축하십시오. 3. 데이터 분석 및 시각화 : Python을 사용하여 데이터를 처리하고 웹 인터페이스를 통해 표시합니다. 4. 머신 러닝 및 AI : 파이썬은 지능형 웹 애플리케이션을 구축하는 데 사용됩니다. 5. 성능 최적화 : 비동기 프로그래밍, 캐싱 및 코드를 통해 최적화

Python vs. C : 성능과 효율성 탐색Python vs. C : 성능과 효율성 탐색Apr 18, 2025 am 12:20 AM

Python은 개발 효율에서 C보다 낫지 만 C는 실행 성능이 높습니다. 1. Python의 간결한 구문 및 풍부한 라이브러리는 개발 효율성을 향상시킵니다. 2.C의 컴파일 유형 특성 및 하드웨어 제어는 실행 성능을 향상시킵니다. 선택할 때는 프로젝트 요구에 따라 개발 속도 및 실행 효율성을 평가해야합니다.

Python in Action : 실제 예제Python in Action : 실제 예제Apr 18, 2025 am 12:18 AM

Python의 실제 응용 프로그램에는 데이터 분석, 웹 개발, 인공 지능 및 자동화가 포함됩니다. 1) 데이터 분석에서 Python은 Pandas 및 Matplotlib를 사용하여 데이터를 처리하고 시각화합니다. 2) 웹 개발에서 Django 및 Flask 프레임 워크는 웹 응용 프로그램 생성을 단순화합니다. 3) 인공 지능 분야에서 Tensorflow와 Pytorch는 모델을 구축하고 훈련시키는 데 사용됩니다. 4) 자동화 측면에서 파이썬 스크립트는 파일 복사와 같은 작업에 사용할 수 있습니다.

Python의 주요 용도 : 포괄적 인 개요Python의 주요 용도 : 포괄적 인 개요Apr 18, 2025 am 12:18 AM

Python은 데이터 과학, 웹 개발 및 자동화 스크립팅 필드에 널리 사용됩니다. 1) 데이터 과학에서 Python은 Numpy 및 Pandas와 같은 라이브러리를 통해 데이터 처리 및 분석을 단순화합니다. 2) 웹 개발에서 Django 및 Flask 프레임 워크를 통해 개발자는 응용 프로그램을 신속하게 구축 할 수 있습니다. 3) 자동 스크립트에서 Python의 단순성과 표준 라이브러리가 이상적입니다.

파이썬의 주요 목적 : 유연성과 사용 편의성파이썬의 주요 목적 : 유연성과 사용 편의성Apr 17, 2025 am 12:14 AM

Python의 유연성은 다중 파리가 지원 및 동적 유형 시스템에 반영되며, 사용 편의성은 간단한 구문 및 풍부한 표준 라이브러리에서 나옵니다. 유연성 : 객체 지향, 기능 및 절차 프로그래밍을 지원하며 동적 유형 시스템은 개발 효율성을 향상시킵니다. 2. 사용 편의성 : 문법은 자연 언어에 가깝고 표준 라이브러리는 광범위한 기능을 다루며 개발 프로세스를 단순화합니다.

파이썬 : 다목적 프로그래밍의 힘파이썬 : 다목적 프로그래밍의 힘Apr 17, 2025 am 12:09 AM

Python은 초보자부터 고급 개발자에 이르기까지 모든 요구에 적합한 단순성과 힘에 호의적입니다. 다목적 성은 다음과 같이 반영됩니다. 1) 배우고 사용하기 쉽고 간단한 구문; 2) Numpy, Pandas 등과 같은 풍부한 라이브러리 및 프레임 워크; 3) 다양한 운영 체제에서 실행할 수있는 크로스 플랫폼 지원; 4) 작업 효율성을 향상시키기위한 스크립팅 및 자동화 작업에 적합합니다.

하루 2 시간 안에 파이썬 학습 : 실용 가이드하루 2 시간 안에 파이썬 학습 : 실용 가이드Apr 17, 2025 am 12:05 AM

예, 하루에 2 시간 후에 파이썬을 배우십시오. 1. 합리적인 학습 계획 개발, 2. 올바른 학습 자원을 선택하십시오. 3. 실습을 통해 학습 된 지식을 통합하십시오. 이 단계는 짧은 시간 안에 Python을 마스터하는 데 도움이 될 수 있습니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

VSCode Windows 64비트 다운로드

VSCode Windows 64비트 다운로드

Microsoft에서 출시한 강력한 무료 IDE 편집기

맨티스BT

맨티스BT

Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

ZendStudio 13.5.1 맥

ZendStudio 13.5.1 맥

강력한 PHP 통합 개발 환경

Dreamweaver Mac版

Dreamweaver Mac版

시각적 웹 개발 도구

MinGW - Windows용 미니멀리스트 GNU

MinGW - Windows용 미니멀리스트 GNU

이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.