V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
davidli
V2EX  ›  Python

入门问题求解答~有关Python中函数传值的问题

  •  
  •   davidli ·
    hmli · 2013-06-11 15:00:39 +08:00 · 3893 次点击
    这是一个创建于 3962 天前的主题,其中的信息可能已经有所发展或是发生改变。
    新人,一直在潜水,第一次提问。
    以前学JAVA,又学了点JS,最近学Python.
    了解到Python中函数如果要使用函数外某变量,那它只是将其值复制一份传入,而非直接将此变量引用。
    这样, 如果我想用一个函数对函数外的值进行修改,应该怎么做?

    比如 已有a=1, b=2,我想写一个swap(a,b), 让这两个数交换其值, 应该怎么写?

    得知可以用global变量,但一是灵活性太差,二是感觉这么小的问题就用到了global,有点杀鸡用牛刀的意味。

    所以请问在Python有没有比较合适的解决此问题的方法?
    11 条回复    1970-01-01 08:00:00 +08:00
    wwwjfy
        1
    wwwjfy  
       2013-06-11 15:03:26 +08:00   ❤️ 2
    1. a, b = b, a

    2. 函数返回值重新赋值

    3. 包在字典或者列表之类的传引用的进去

    具体情况具体分析
    davidli
        2
    davidli  
    OP
       2013-06-11 15:08:29 +08:00
    @wwwjfy
    a,b = b,a !!!
    还能这么用!!
    用惯了JAVA死板的语法,一时半会适应不能
    但请问这样为什么不会出现a =b, b=b的错误?
    wwwjfy
        3
    wwwjfy  
       2013-06-11 16:00:27 +08:00
    @davidli 没研究那么深

    python本来就是支持这种多赋值的,也没有执行顺序的差别,不会出现那种错误...

    其实a, b是(a, b), c = a, b ==> c = (a, b)

    充其量算是语法糖,跟语言本质没什么关系
    swulling
        4
    swulling  
       2013-06-11 16:06:14 +08:00   ❤️ 1
    Python分可变对象和不可变对象,可变对象你是不能用swap()来修改其值得
    swulling
        5
    swulling  
       2013-06-11 17:13:05 +08:00
    突然发现回答写错了。。可变对象 ---> 不可变对象

    不过应该都知道<_<
    ruoyu0088
        6
    ruoyu0088  
       2013-06-11 18:45:36 +08:00   ❤️ 2
    a, b = b, a
    这句执行时,先运行b, a, 得到一个tuple对象,然后由于等号左边有两个名字,因此又将tuple对象打开。相当于执行以下两句:
    t = b, a
    a, b = t
    firstway
        7
    firstway  
       2013-06-11 23:24:28 +08:00
    我的理解是,lz对swap(a,b)只是一个举例,lz问题的核心(正如swulling所说)其实就是“可变对象和不可变对象”的理解。lz可以找找“可变对象和不可变对象”相关文章看看。
    firstway
        8
    firstway  
       2013-06-11 23:32:28 +08:00
    对于不可变对象,比如数值类型,函数传递都是是值传递,也就是复制一份,函数内任何修改对函数外没有影响,除了global。
    如果是可变对象,比如list,可以理解为引用传递,函数内的In-Place Changes就会修改引用本身的内容。比如:
    def my_add(L):
    L[0] = L[0]+100
    a = [8,9,10]
    my_add(a)
    print(a) ## a = [108,9,10]
    y0
        9
    y0  
       2013-06-12 00:00:10 +08:00
    “用一个函数对函数外的值进行修改” 这种行为本来就应该避免。
    好的 “函数” 应该是不保存任何状态,每次运行结果都一样的。
    运行结果不一样的,那叫指令而不是函数,需要保存状态的话用闭包。

    你需要改变的是这种思路而不是找个办法修改外部的值。

    实在有必要的话,让函数返回需要的值,再 unpack. 和 swap 类似。比如

    def h(a,b,c):
    ....xxxxxxxxxxx
    ....xxxxxxxxxxx
    ....return new_a, new_b, new_c

    a, b, c = h(a, b, c)
    glasslion
        10
    glasslion  
       2013-06-21 16:08:51 +08:00
    @firstway 不可变对象还是应用传递,不会发生复制。
    itfanr
        11
    itfanr  
       2014-02-15 15:41:06 +08:00
    楼主的疑惑和我想的也是完全一样,我通过以下的回复渐渐明白了。python是把数字上面挂变量标签,不是往变量盒子里面放数据,和C/JAVA完全不同的。

    @y0 "用一个函数对函数外的值进行修改" C++等语言,只能传地址进去。。。。不过python就应该发挥它的长处
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   958 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 21:33 · PVG 05:33 · LAX 14:33 · JFK 17:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.