add by zhj: 在Python文档中清楚的说明了默认参数是怎么工作的,如下

"Default parameter values are evaluated when the function definition is executed. This means that the expression is evaluated once, when the function is defined, and that the same “pre-computed” value is used for each call. This is especially important to understand when a default parameter is a mutable object, such as a list or a dictionary: if the function modifies the object (e.g. by appending an item to a list), the default value is in effect modified. This is generally not what was intended. A way around this is to use None as the default, and explicitly test for it in the body of the function

def whats_on_the_telly(penguin=None):
if penguin is None:
penguin = []
penguin.append("property of the zoo")
return penguin

"

参见https://docs.python.org/2/reference/compound_stmts.html#function-definitions

原文:Python函数参数默认值的陷阱和原理深究

这个问题的答案在 StackOverflow 上可以找到答案。这里将得票数最多的答案最重要的部分摘录如下:

Actually, this is not a design flaw, and it is not because of internals, or performance.
It comes simply from the fact that functions in Python are first-class objects, and not only a piece of code.
As soon as you get to think into this way, then it completely makes sense: a function is an object being evaluated on its definition; default parameters are kind of “member data” and therefore their state may change from one call to the other - exactly as in any other object.
In any case, Effbot has a very nice explanation of the reasons for this behavior in Default Parameter Values in Python.
I found it very clear, and I really suggest reading it for a better knowledge of how function objects work.

在这个回答中,答题者认为出于Python编译器的实现方式考虑,函数是一个内部一级对象。而参数默认值是这个对象的属性。在其他任何语言中,对象属性都是在对象创建时做绑定的。因此,函数参数默认值在编译时绑定也就不足为奇了。
然而,也有其他很多一些回答者不买账,认为即使是first-class object也可以使用closure的方式在执行时绑定。

This is not a design flaw. It is a design decision; perhaps a bad one, but not an accident. The state thing is just like any other closure: a closure is not a function, and a function with mutable default argument is not a function.

甚至还有反驳者抛开实现逻辑,单纯从设计角度认为:只要是违背程序猿基本思考逻辑的行为,都是设计缺陷!下面是他们的一些论调:
> Sorry, but anything considered “The biggest WTF in Python” is most definitely a design flaw. This is a source of bugs for everyone at some point, because no one expects that behavior at first - which means it should not have been designed that way to begin with.

The phrases “this is not generally what was intended” and “a way around this is” smell like they’re documenting a design flaw.

好吧,这么看来,如果没有来自于Python作者的亲自澄清,这个问题的答案就一直会是一个谜了。

Python函数参数默认值的陷阱和原理深究(转)的更多相关文章

  1. Python函数参数默认值的陷阱和原理深究"

    本文将介绍使用mutable对象作为Python函数参数默认值潜在的危害,以及其实现原理和设计目的 本博客已经迁移至: http://cenalulu.github.io/ 本篇博文已经迁移,阅读全文 ...

  2. ES6函数参数默认值作用域的模拟原理实现与个人的一些推测

    一.函数参数默认值中模糊的独立作用域 我在ES6入门学习函数拓展这一篇博客中有记录,当函数的参数使用默认值时,参数会在初始化过程中产生一个独立的作用域,初始化完成作用域会消失:如果不使用参数默认值,不 ...

  3. python函数参数默认值及重要警告

    最有用的形式是对一个或多个参数指定一个默认值.这样创建的函数,可以用比定义时允许的更少的参数调用,比如: def ask_ok(prompt, retries=4, reminder='Please ...

  4. java函数参数默认值

    java函数参数默认值 今天,需要设定java函数参数的默认值,发现按照其它语言中的方法行不通 java中似乎只能通过函数的重载来实现 函数参数默认代码

  5. ES6学习 --函数参数默认值与解构赋值默认值

    1. ES6的解构ES6中引入了解构赋值的操作,其作用是:将值从数组Array或属性从对象Object提取到不同的变量中 即分为两种情况:从数组Array中解构,以及从对象Object中解构 ①.从数 ...

  6. ES6 - 函数扩展(函数参数默认值)

    函数参数默认值 ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console.log(x, y); ...

  7. 【C#基础概念】函数参数默认值和指定传参和方法参数

    函数参数默认值和指定传参 最近在编写代码时发现介绍C#参数默认值不能像PL/SQL那样直接设置default,网上也没有太多详细的资料,自己琢磨并试验后整理成果如下: C#允许在函数声明部分定义默认值 ...

  8. ES6 学习笔记之三 函数参数默认值

    定义函数时为参数指定默认值的能力,是现代动态编程语言的标配.在ES6出现之前,JavaScript是没有这种能力的,框架为了实现参数默认值,用了很多技巧. ES6 的默认参数值功能,与其他语言的语法类 ...

  9. ES6中函数参数默认值问题

    参数默认值 // 以前的参数默认值写法 let fn = (a, b) => { a = typeof a === "undefined" ? 10 : a b = type ...

随机推荐

  1. VS2017、netcore版本更新升级

    VS2017 剩下的就是下一步了. netcore 访问:https://www.microsoft.com/net/download/archives 找到对应版本(最新版本) 下载安装就可以了 装 ...

  2. springboot学习(七) 使用JdbcTemplate

    1.对内嵌数据库的支持 内嵌数据库通常用于开发和测试环境,不推荐用于生产环境.Spring Boot提供自动配置的嵌入式数据库有H2.HSQL.Derby,你不需要提供任何连接配置就能使用. 例子: ...

  3. OPPO.1107刷机笔记

    手动 转移任意APP为系统APP的方法流程简述 宗旨: 保持和系统原本同目录下的文件各种设置(权限,所有者,SE上下文),目录结构保持一致即可! 从 /data/app/里将对应的APP文件移动到 / ...

  4. ipk CONTROL 目录的作用

    CONTROL文件夹下的文件意义preinst        - shell script,在ipk包开始安装前执行;postinst       - shell script,在ipk包安装后执行; ...

  5. Linux下查看分区UUID

    有两种方法: 1.#:blkid 2.ls -l /dev/disk/by-uuid/

  6. MFC 改变控件的大小和位置

    mfc 改变控件大小和位置用到的函数: ) void MoveWindow(int x, int y, int nWidth, int nHeight); ) void MoveWindow(LPCR ...

  7. 超级拷贝scp

    scp -r 超级拷贝,其是ssh的一个组件,通过ssh访问来拷贝文件.首先保证已安装openssh-server. 用法:scp -r 目标用户名@目标ip:目标文件绝对路径  存放位置 $ scp ...

  8. PHPWord使用方法

    官方文档  github地址 一.安装 直接使用composer安装,链接地址 composer require phpoffice/phpword 二.简单使用 require_once 'PhpO ...

  9. 基于springCloud的分布式架构体系

    Spring Cloud作为一套微服务治理的框架,几乎考虑到了微服务治理的方方面面,之前也写过一些关于Spring Cloud文章,主要偏重各组件的使用,本次分享主要解答这两个问题:Spring Cl ...

  10. Servlet 客户端 HTTP 请求

    当浏览器请求网页时,它会向 Web 服务器发送特定信息,这些信息不能被直接读取,因为这些信息是作为 HTTP 请求的头的一部分进行传输的.您可以查看 HTTP 协议 了解更多相关信息. 以下是来自于浏 ...