精华内容
下载资源
问答
  • Python函数调用

    2018-08-14 23:38:00
    1.python函数基础 函数名: fun 函数体:1~3行 返回值:2 调用函数:fun() ,只有见到这个括号(),程序会根据函数名从内存中找到函数体,然后执行它。 2.函数执行顺序 下面fun将上面fun覆盖掉了,...

    转载自链接: http://www.cnblogs.com/feixuelove1009/p/5541632.html

    1.python函数基础

    函数名: fun

    函数体:1~3行

    返回值:2

    调用函数:fun() ,只有见到这个括号(),程序会根据函数名从内存中找到函数体,然后执行它。

     

    2.函数的执行顺序

    下面的fun将上面的fun覆盖掉了,因此,在Python中代码的放置位置是有要求的,不能随意摆放,函数体要放在被调用的语句之前。

     

    3.函数的调用

    第一种情况:

    x(f),注意:x(f)中的f没有加括号(),即f为参数。将f作为参数传入x(),x()中的y()函数返回的是y即函数名所以没有执行y函数。所以最终打印出为无结果。

     

    第二种情况:

    x(f()),注意:x(f())中f后面是有括号的,即f作为函数传给x。将f()函数传给x()函数,先执行f()函数打印出2,再执行x()函数,因为x()中的y()函数返回的是y即函数名所以没有执行y函数。所以最终打印结果为2。

     

    第三种情况:

    x(f),注意:x函数中的y函数返回的值是y函数,即return y()。x(f)中f作为参数传给x函数,所以f()函数就不执行了,执行x函数,因为return y(),所以执行y函数打印出1。最终打印结果为1。

     

    第四种情况:

    x(f()),注意:x(f())中f后面是有括号的,即f作为函数传给x;x函数中的y函数返回的值是y函数,即return y()。将f()函数传给x()函数,先执行f()函数打印出2,再执行x函数,因为return y(),所以执行y函数打印出1。最终执行打印结果为2 1。

     

    第五种情况:

    x(f),注意:x(f)中f后面没有括号,即f作为参数传入x()函数。将f作为参数带入x函数执行,因为return y()所以执行y函数打印出1;再执行语句,此时相当于func()=f(),即开始执行f()函数打印出2。所以最终打印结果为1 2。

    以上是按照我自己理解来总结的,不对或者有补充的地方欢迎指出来~~

    声明:如需转载,请注明来源!

    转载于:https://www.cnblogs.com/cmdegr/p/9478819.html

    展开全文
  • C++之python函数调用

    2010-06-06 00:32:22
    C++之python函数调用 习惯C++的内存分配释放,突然间不用释放,感觉很蹊跷,上网查发现也没有释放函数。如果真这样的话,是很可怕的,因为无法自己管理内存,但是我相信编译器作者的垃圾回收机制,所以OK,不管!...
  • python 函数调用顺序

    2018-01-06 18:26:00
    def foo(): print ('in the foo') bar() def bar(): print ('in the bar') ...1.foo函数进入内存 ...4.调用已经进入内存的foo函数,运行到第三行,这时因为第二部bar已经进入内存了,所以直接可以引用bar函...
    def foo():
        print ('in the foo')
        bar()
    def bar():
        print ('in the bar')
    foo()

    1.foo函数进入内存

    2.bar函数进入内存

    3.foo()开始实例化使用foo函数。

    4.调用已经进入内存的foo函数,运行到第三行,这时因为第二部bar已经进入内存了,所以直接可以引用bar函数。

    总结:python 函数调用的顺序是先把函数的虚拟先放进去,从上到下,一直放到foo()函数之前。然后遇到foo函数就开始跑这个foo函数。foo之后的函数还没有进入。

    当然这里面还有最重要一点不是废话,其实上面的东西很浅显基本废话。这句不是废话说的是,函数放入内存,只是形式上放一下,并不是真正跑他的内容,这样就导致了第三行bar()其实是在第四行def bar()被装进内存后才进行启动的。上面4个步奏中的第一步foo函数进入内存只是形式进入,只有当3foo()开始第三行的bar(),也就是真正的第一次运行第三行的bar().

    比如下面 的就是错误

    def foo():
        print ('in the foo')
        bar()
    foo()
    def bar():
        print ('in the bar')

     

    转载于:https://www.cnblogs.com/zhangbo2008/p/8214938.html

    展开全文
  • python函数调用时参数传递方式 C/C++参数传递方式 对于C程序员来说,我们都知道C在函数调用时,采用的是值传递,即形参和实参分配不同的内存地址,在调用时将实参的值传给实参,在这种情况下,在函数内修改形参并...

    python函数调用时参数传递方式

    C/C++参数传递方式

    对于C程序员来说,我们都知道C在函数调用时,采用的是值传递,即形参和实参分配不同的内存地址,在调用时将实参的值传给实参,在这种情况下,在函数内修改形参并不会影响到实参,但是这样带来一个问题,如果我们需要刻意地对实参进行修改,就不得不传递实参的指针到函数,然后在函数中修改指针指向的数据,以达到修改实参的目的。

    后来,C++中引入了引用这个概念,即在函数定义时,在形参前加一个&符号,表示传递参数的引用,在写法上,除了多出一个&符号,其他部分和C中传值调用一样,但是实际确是达到了可以在函数内修改实参内容的目的。这种参数传递的方式被称为传引用。

    python的参数传递

    说完了C/C++的参数传递方式,那么python中参数传递到底是传值还是传引用呢?我们来看两个实例:
    test1.py:

    def test(num):
        num += 10
    x = 1
    test(x)
    print x

    输出结果:

    1

    test2.py:

    def test(lst):
        lst[0] = 4
        lst[1] = 5
    tlist = [1,2]
    test(tlist)
    print tlist

    输出结果:

    [4,5]

    可以看到,在上述代码test1.py中,在函数中修改传入的x的值,函数执行完之后,x并没有改变,至少对于int型变量而言,python函数调用为传值。

    在代码test2.py中,在函数中修改传入的tlist的值,函数执行完,list的内容却被函数修改了,从这里又可以看出,对于list类型而言,python函数调用为传引用。

    看到这里就很疑惑了,python的函数调用到底是传值还是传引用?

    python的变量内存模型

    要搞清楚python的函数调用时传值还是传引用,这还得从python的变量内存模型说起,作为一个C/C++程序员,对于变量的理解就是CPU会为每个变量分配独立的内存空间,在变量生存周期结束时内存空间被收回。

    但python却使用了另一种完全不同的机制,对于python而言,一切皆对象,python为每个对象分配内存空间,但是并非为每个变量分配内存空间,因为在python中,变量更像是一个标签,就像在现实生活中,一个人可以有多种身份标签,比如:XX的父亲,XX的儿子,XX的工程师,X地志愿者等等,但对应的实体都是同一个人,只占同一份资源。

    为了验证这个问题,我们可以做下面的实验:

    x = 1
    print(id(x))
    print(id(1))
    print(id(5))
    x= 5 
    print(id(x))
    print(id(1))
    print(id(5))

    输出:

    166656176
    166656176
    166656128
    
    166656128
    166656176
    166656128  

    从输出可以看出,当我们将x变量的值由1变成5时,x的地址刚好从对象1的内存地址变成了对象5的内存地址。

    Tips:
        对于C/C++程序员来说,这段代码并不好理解,变量的值被改变时,竟然是变量的地址变化而不是原变量地址上的值变化!而且,为什么系统会为字面值1和5分配内存空间,这在C/C++中是不存在的!  
        所以我们要从python变量内存角度来理解:对象1和对象5早就在内存中存在,而变量x先是指向1的标签,在赋值后变成了指向5的标签。

    更多内存细节可以参考我另一篇博客:python变量的内存机制

    python的间接引用机制

    可变类型和不可变类型

    在python中将类型分为了可变类型和不可变类型,分别有:

    可变类型:列表,字典

    不可变类型:int、float、string、tuple

    我们可以这样简单地来理解可变类型和不可变类型:在修改该类型变量时是否产生新对象,如果是在原对象上进行修改,为可变对象,如果是产生新的对象,则是不可变对象。

    那么怎么判断是否产生新的对象呢?我们可以用python内建id()函数来判断,这个函数返回对象在内存中的位置,如果内存位置有变动,表明变量指向的对象已经被改变。

    python传参时可变类型和不可变类型的区别

    事实上,对于python的函数传递而言,我们不能简单地用传值或者传址来定义参数传递,我们从上一部分中可变类型和不可变类型的角度来分析:

    • 在参数传递时,实参将标签复制给了形参,这个时候形参和实参都是指向同一个对象。
    • 在函数内修改形参,
      • 对于不可变类型变量而言:因为不可变类型变量特性,修改变量需要新创建一个对象,形参的标签转而指向新对象,而实参没有变
      • 对于可变类型变量而言,因为可变类型变量特性,直接在原对象上修改,因为此时形参和实参都是指向同一个对象,所以,实参指向的对象自然就被修改了。
        到这里,应该就不难理解为什么在"python的参数传递"部分,test1.py和test2.py执行完两种完全不同的结果了(test1.py传入不可变类型int,实参未被函数修改。而test2.py传入可变类型list,实参被修改)。

    不仅仅是参数传递

    在上面我们谈论了可变参数和不可变参数在参数传递时的行为,其实,这种机制存在于整个python环境中,而不仅仅是参数传递中,我们看下面的例子:

    list1 = [1,2]
    list2 = list1
    list1[0] = 3
    print list1
    print list2

    输出:

    [3, 2]
    [3, 2]

    在上述示例中,令list2 = list1,因为根据之前的理论,list2和list1指向同一个对象,所以修改list1时同时也会修改list2,这种机制在一定程度上可以提高资源的重复利用,但是对C/C++程序员来说无疑算是一个陷阱。

    可变类型和不可变类型混合的情况

    我们人为地将变量分为可变类型和不可变类型,然后分类讨论,以为就万事大吉了,但是实际情况总是复杂的,我们可以来看看下面的例子:

    lst = [(1,2),3]
    tup = ([1,2],3)

    像这种情况中,两种类型糅杂在一起,那怎么去区分他们到底属于哪个阵营呢?这样的变量在修改时会不会创建新的对象呢?我们再来试一试:

    tup = ([1,2],3)
    tup1 = tup
    tup1[0][0] = 3
    print tup
    print tup1

    输出结果:

    ([3,2],3)
    ([3,2],3)

    这个结果就很有意思了,元组的第一个元素为一个列表,且令tup1 = tup,即两个变量指向同一个对象,我们修改了元组的第一个元素(列表)的第一个元素,结果两个元组的数据都变了。由此引出两个问题:

    • 为什么元组内的数据可以修改?
    • 作为一个不可变类型变量,为什么我们修改元组的成员时,不会创建一个新的对象而是在原对象上修改,导致另一个指向这个对象的变量取值也发生了变化?

    对于这个问题,我们可以这样去理解:在定义tup变量时,此前内存中没有tup对象,所以系统需要新建一个tup对象,对于tup[0]即[1,2],系统会再去找是否存在这样的对象,如果存在,直接引用原对象,如果不存在,再创建新的对象,对于tup[1]即3,也是同样的道理。

    所以,事实上,tup变量只是一个引用,tup[0]同时也只是个引用,tup[1]照样如此,所以,创建一个符合类型的变量并非我们所想的在内存中专门开辟一片区域来放置整个对象,而是在不断地引用其他对象。

    所以,对于问题1,为什么元组内的数据可以修改?答案是,整个元组并非一个统一的整体,我们修改的是tup[0]的元素,即一个列表变量,自然可以修改,
    注意:[0,1]这个整体属于元组的元素,是不可修改的,即我们不能将[0,1]整体替换成其他,但是单独的0,1属于列表的元素,是可以修改的。

    对于问题2,既然我们修改的列表的元素,列表是可变参数类型,那么自然在原对象上修改而非创建新对象。

    现实中的各种情况

    上面说到了python传递参数的特性,那么如果我们要在函数中修改一个不可变对象的实参,又或者是在函数中不修改可变类型的实参,那该怎么做呢?
    首先,如果要在函数中修改一个不可变参数的实参,最简单也最实用的办法就是传入这个参数同时返回这个参数,因为虽然是同一个变量,在传入和返回时这个变量已经指向了不同的对象:

    def test(num):   #num参数指向对象5   
        mum += 10    #num参数指向新对象15
        return num   #返回num,此时num为15
    print test(5)

    然后,如果要在函数中不修改可变参数的实参,这个时候就需要引用另一个模块:copy,就是重新复制出另一个可变类型参数,我们可以看下面的例子:

    import copy
    lst = [1,2]
    lst_cp = copy.copy(lst)
    print id(lst)
    print id(lst_cp)

    输出结果:

    3072211148
    3072211340

    从上述示例可以看出,copy过程中系统复制了一个新的对象,而不是简单地引用原来对象(两个变量指向数据地址不一样)。
    但是需要注意的是,copy只对可变类型变量才创建新的对象,而对不可变类型变量,并不创建新的对象,大家可以去试试。

    copy复制依然可能存在问题

    在可变类型和不可变类型混合的情况下,我们知道了,一个变量很可能并非仅仅指向一个完整的对象,变量的子元素依然存在引用的情况,比如在lst = [[1,2],3)]中,lst[0]就是引用了别处的对象,而非在内存中完全存在一个单独的[[1,2],3]对象,那么,如果使用copy对lst进行复制,对于lst[0],是仅仅复制了引用,还是复制了整个对象呢?我们可以看下面的例子:

    import copy
    lst = [[1,2],3]
    lst_cp = copy.copy(lst)
    print id(lst)
    print id(lst_cp)
    print id(lst[0])
    print id(lst_cp[0])

    输出结果:

    3072042988
    3072043404
    3072043020
    3072043020

    从结果可以看出,对于lst列表,仅仅是复制了lst对象,lst[0]仅仅是复制了引用。这其实违背了我们的本意,如果我们要完整地复制整个对象,那又改怎么做呢?

    deepcopy

    对于上面问题的解决方案是:使用copy模块的deepcopy方法,相对于copy方法(通常被称为浅拷贝),deepcopy(通常被称为深拷贝),浅拷贝就像上述的例子一样,复制出一个新的对象,但是目标对象中的子对象可能是引用。而deepcopy则是完全复制一个对象的所有内容。

    好了,关于python函数调用时参数调用方式的讨论就到此为止了,如果朋友们对于这个有什么疑问或者发现有文章中有什么错误,欢迎留言

    个人邮箱:linux_downey@sina.com
    原创博客,转载请注明出处!

    祝各位早日实现项目丛中过,bug不沾身.
    (完)

    转载于:https://www.cnblogs.com/downey-blog/p/10483216.html

    展开全文
  • python的参数传递是值传递还是引用传递?...值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间来存放由主调函数放进来实参值,从而想成为了实...

    python的参数传递是值传递还是引用传递??
    函数参数传递机制,传值和引用的是什么意思?

    函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题。基本的参数传递机制有两种:值传递和引用传递。

    值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间来存放由主调函数放进来的实参的值,从而想成为了实参的一个副本。值传递的特点是被调函数对形势参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。

    引用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做任何的操作都影响了主调函数中的实参变量。

    在python中,可以有多个引用同时指向一个内存。

    python不允许程序员选择采用传值还是传引用。python参数传递采用的肯定是“传对象引用”的方式。这种方式相当于传值和传引用的一种综合。如果函数收到的是一个可变对象(字典、列表)的引用,就能修改对象的原始值–相当于‘传引用’来传递对象。如果函数收到的是一个不可变对象(数字、字符或元组)的引用,就不能直接修改原始对象–相当于通过‘值传递’来传递对象。

    展开全文
  • 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信方法问题。基本参数传递机制有两种:值传递和引用传递。  值传递(passl-by-value)过程中,被调函数的形式参数...
  • Python入门基础篇 No.62 —— 递归函数_函数调用内存分析_栈帧创建 文章目录Python入门基础篇 No.62 —— 递归函数_函数调用内存分析_栈帧创建前言一、递归函数总结 前生篇:eval()函数用法 前言 一、递归...
  • 第86课时: 函数: 递归函数 函数调用内存分析 栈帧创建 递归函数: 自己调用自己函数。在函数体内自己条用自己函数。 测试:在函数中调别函数。(tt01 中调用 tt02) def tt01(): print('wlzznb') tt...
  • python函数的调用

    2019-05-22 18:06:00
    转载自https://www.cnblogs.com/mumunansheng/p/6278814.html1.python函数基础函数名: fun函数体:1~3行返回值:2调用函数:fun() ,只有见到这个括号(),程序会根据函数名从内存中找到函数体,然后执行它。2.函数...
  • 不可变对象(immutable):int、string、float、number、tuple ...但是对于list来说,列表传递给函数的是一个指针,指针指向序列在内存位置,在函数中对表操作将在原有内存中进行,从而印象...
  • Python 函数内存分析

    2019-05-23 23:15:53
    067.函数的基本概念_内存分析_函数的分类_定义和调用 a.内置函数,标准库函数,第三方函数,用户自定义函数; b.函数的定义和调用: def 函数名([参数列表]): 函数体/若干语句 def fun(): print("***...
  • 1、python函数基础 函数名: fun 函数体:1~3行 返回值:2 调用函数:fun() ,只有见到这个括号(),程序会根据函数名从内存中找到函数体,然后执行它 2.函数执行顺序 下面fun将上面fun覆盖掉了,因此,在...
  • 函数内存分配(调用列表时,不用return就可以改变列表) 例题1 #1. 将函数代码加载到内存代码区 def func01(p1): print("func01执行了,参数是:" + p1) return 100 data01 = "悟空" #2. 调用函数时,会开辟一块...
  • Python元素有可变和不可变之分,如整数、浮点数、字符串、元组都属于不可变元素。列表和字典属于可变。  对于整数、浮点数不可变:  “=”作用是将对象引用过与内存对象进行绑定,既然整数是不可...
  • python函数

    2020-10-14 18:22:54
    一.什么是函数 所谓函数,就是把具有...函数调用的本质(内存模型) 引用传递和值传递 Python函数的参数 函数递归 * 有无参数 |-- 有参函数 |-- 无参函数 |-- 是否存在返回值 |-- 有返回值的函数 |-- 无返回值的函数
  • Python函数的使用

    2020-10-21 14:40:35
    什么是函数?在python中具有名称的某段代码用来实现想要的功能指令的集合。 具体来说:函数是一个功能,是一个行为,是一个...2、函数调用的本质(内存模型) 3、引用传递和值传递 4、python函数的参数 5、函数递归 有
  • 主要是解释前几章看不懂的函数调用 1.python函数基础 def uop(): print(1) return 2 uop() 函数名: uop 函数体:1~3行 返回值:2 调用函数:uop() ,只有见到这个括号(),程序会根据函数名从内存中找到函数体...
  • Python 函数的使用

    2020-10-14 15:45:51
    什么是函数? 在python中具有名称的某段代码用来实现想要的功能指令的集合。 具体来说:函数是一个功能,是一个行为,是一个动作。...2、函数调用的本质(内存模型) 3、引用传递和值传递 4、python
  • #闭包:嵌套函数,内部函数调用外部函数变量 # def outer(): # a = 1 # def inner(): # print(a) # inner() # outer() def outer(): a = 1 def inner(): print(a) return inner...
  • 知识来源,尚学堂高琪老师讲解 代码: #测试函数也是对象 ...栈内存会创建 test01变量,保存堆内存函数的地址。 2.函数的调用 test01() 保存地址名称加上(),就是调用函数的意思。 .
  • Python函数

    2019-04-20 19:30:00
    函数调用 : 函数名 函数的内存地址 传实参 接收返回值 函数名 函数名可以像一个变量一样去使用 -----> 函数是第一类对象 函数名可以赋值 函数名可以作为容器类型中的一项 函数名可以作为函数的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,622
精华内容 648
关键字:

python函数调用的内存

python 订阅