python局部变量和全局变量的问题

shell33168 2017-11-23 07:44:11
为什么在函数里面修改list,list前后都改变了;但是在函数里面修改变量,在函数外面却无法修改呢?

def changeme( mylist ):
"修改传入的列表"
mylist.append([1,2,3,4]);
print "函数内取值: ", mylist
return
#
# # 调用changeme函数
mylist = [10,20,30];
changeme( mylist );
print "函数外取值: ", mylist
#


def sum( total ):
#返回2个参数的和."
total = 30 # total在这里是局部变量.
print "函数内是局部变量 : ", total
# return total;
return
total=0
sum(total)
#调用sum函数
print "函数外是全局变量 : ", total



结果:
函数内取值: [10, 20, 30, [1, 2, 3, 4]]
函数外取值: [10, 20, 30, [1, 2, 3, 4]]
函数内是局部变量 : 30
函数外是全局变量 : 0
...全文
520 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
混沌鳄鱼 2017-11-24
  • 打赏
  • 举报
回复
我来说两句: 通常大家所说的函数调用时的传值和传引用都是借用C语言或其它一些静态语言的概念。 因为在C语言中变量就是实际在内存某地址空间上存储值。 函数调用时的实参传值即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。 传引用则是传了实参变量指针(内存地址) 然而Python是完全不同于C语言的实现机制。Python中的变量和C语言中的变量是很不同的。 在Python中一切都是对象,并不存在C语言中的所谓的值, 比如 >>> dir(2) 就能看到一大堆属性。

>>> dir(2)
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
var = 1234 这个变量 声明和赋值过程实际上是, 先创建1234这个整数对象,然后再把这个对象的引用绑定给var这个字符串。

>>> var = 1234
>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'var': 1234}
再看一个例子

>>> a = 257
>>> id(a)
2845238190192
>>> def foo(arg): print(id(arg))

>>> foo(a)
2845238190192
>>> b = [1,2,3]
>>> id(b)
2845238037832
>>> foo(b)
2845238037832
>>> 
从上面例子可以看到, 无论是不可变对象还是可变对象,传参的时候都是传的对象的引用。 所以严格地说: Python的参数传递既不是传值(pass-by-value),也不是传引用(pass-by-reference),而是对象的引用(pass-by-object-reference),即传递的是一个对象的内存地址。
oyljerry 2017-11-24
  • 打赏
  • 举报
回复
python中函数都是传值,只不过对于list参数,mylist是指向列表的引用,所以传递的是引用的值,因而函数内部通过这个值可以修改引用的链表,函数返回后,也是修改的数据 而total是基本数据类型,函数传递的也是它的值,同时它是不可变对象,因而修改它的话,是修改复制后的值,而函数出来后,原来的值不会变
sprawling 2017-11-23
  • 打赏
  • 举报
回复
#!/usr/bin/env python
# -*- coding:utf-8 -*-

def changeme( mylist ):
   "修改传入的列表"
   print id(mylist)
   mylist.append([1,2,3,4]);
   print "函数内取值: ", mylist
   print id(mylist)
   return
#
# # 调用changeme函数
mylist = [10,20,30];
changeme( mylist );
print "函数外取值: ", mylist
#
print id(mylist)
 
 
def sum( total ):
   #返回2个参数的和."
   total = 30 # total在这里是局部变量.
   print "函数内是局部变量 : ", total
   print id(total)
   # return total;
   return
total=0
sum(total)
print id(total)

#调用sum函数
print "函数外是全局变量 : ", total


sprawling 2017-11-23
  • 打赏
  • 举报
回复
第二个function里面,total是参数,
赵根硕 2017-11-23
  • 打赏
  • 举报
回复
这个问题我觉得可以这样理解,因为我们操作列表的时候操作的直接是这个列表的内存地址上的数据,所以不管我们在什么地方来操作一个列表他的值都会变,而对于一个普通的变量如果想像列表这样,那就必须进行全局变量的声明才可以生效。

37,719

社区成员

发帖
与我相关
我的任务
社区描述
JavaScript,VBScript,AngleScript,ActionScript,Shell,Perl,Ruby,Lua,Tcl,Scala,MaxScript 等脚本语言交流。
社区管理员
  • 脚本语言(Perl/Python)社区
  • IT.BOB
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧