PHP和Python中的引用机制

来源:互联网 发布:吉林大学网络教育电话 编辑:程序博客网 时间:2024/06/10 02:23
PHP 和 Python 语言中引用是非常重要的一个概念,这个概念对于理解两门语言非常重要,会让你更深刻的认识到两门语言的本质,所以简单的谈一谈。先说结论,Python 语言中一切都是对象,理解起来觉得更合理;PHP 则是混搭机制,对于引用的处理让人很困惑。
  Python 中的引用
  在 Python 中一切都是对象,整型值、字典、元祖都是对象,连函数、类本身也是对象,定义一个函数,即使程序没有调用,可在执行的时候,其本身也是一个对象。
  对象分三部分,身份,类型和值,身份就是一个变量标识符,由 Python 解析器维护,可以通过 id() 函数获取变量编号。而值是具体存储的内容(在内存中有一个地址),通过变量名将具体的对象关联起来(可以说是引用)。当 Python 发现值(内容)没有变量引用了,就会进行回收。
  结论在 Python 中,变量赋值和函数参数传递都是引用关系。
  (1)看看一个赋值或者函数参数传递发生了什么:
  m = "hello"n = m
  上述语句 m 和 n 变量其实是引用的同一块内容,m 和 n 不分主次,对它们进行查询,就是对 "hello" 这个内容体进行查询。
  (2)当修改一个变量值的时候发生了什么?
  这里要区分下可变对象和不可变对象,可变对象表示变量名赋值就是直接在对应的内容体进行操作;而不可变对象表示变量对应的内容体是只读的(假如重新赋值实际是从新开辟一块内存区)。
  在 Python 中整型和字符串类型是不可变对象,其他是可变对象,看几个例子:
  m = "hello"n = m n = "good"
  这段代码中对 n 进行重新赋值操作的时候,不是在 "hello" 这个内容体上进行修改,而是重新创建了一个内容体"good",n 变量则引用了它。
  m = []
  n = m
  n.append(10)
  print m
  对于可变对象来说,上述代码中,不管对 m 还是 n 进行更新,影响的是同一块内容体。
  下面看几个例子,来更深刻的理解。
  Python 中的函数传递
  理解了变量赋值,其实也理解了函数传递,原理是一致的,就是变量和对象的引用关系(绑定)。
  (1)简单的函数传递
  def fun(m):
  m.append(10)
  o = []
  fun(o)print o
  o 这个实参和函数内的 m 形参引用的是同一个内容体,这个普通的赋值其实是一样的处理机制。
  (2)复杂点的例子
  class classobj(object):
  v = []
  def fun(o) :
  o.v.append(1)
  x =  o.v
  return x
  o = classobj()
  s = fun(o)print s ,o.v
  o.v.append(2)print s ,o.v
  s.append(3)print s ,o.v
  上面的代码中,不管是对自定义类的实例属性(o.v)进行操作,还是对函数返回的变量(s)进行操作,引用的都是同一个内容存储体。
  (3)更复杂的例子
  上面说了,函数定义过程中一个形式参数,就算函数没有被调用,在函数这个命名空间内,这个形式参数也是存在的(由 Python 维护)。
  def fun(s=[]):
  s.append(10)
  return s
  o1 = fun()
  print o1
  o2 = fun()
  print o1,o2
  可以看下结果,两次函数调用,函数体内部指向的对象都是同一个,不管函数调用多少次,其形参的 id 值是一样的,其引用的内容体一直存在。
  PHP 中的引用
  PHP 刚出来的时候,为了简单,任何的赋值、函数传递都是拷贝方式的,虽然可能很耗费空间并降低了处理速度,但是对于编程来说却降低了难度。比如下面的代码
  $a = "china";
  $b = $a ;
  $b 和 $a 完全没有关系,操作的是两块内存地址,相当与 $b 先读取 $a 的内容,然后自己存储一份。
  PHP 作为一门语言,一直在演化,也有了引用的概念,但是需要通过 & 符号来显示的指明,属于一个语法糖。比如说下面的代码:
  $a = "china";$b = &$a ;$b = "world";
  echo $a . "_" . $b ;$a = "good";echo $a . "_" . $b ;
  通过 & 符号,则代表 $a 和 $b 指向的是同一块内容。
  引用的好处其实很简单,第一是节省内存空间,比如在函数调用中,假如某个参数变量对应的值有 1K,假如不使用引用传递,则在函数执行的时候,就要额外拷贝 1K 的内容,这样就节省了空间;第二就是提高处理速度,内存的拷贝必然会消耗 CPU 处理时间。
  使用引用固然高效,但是也要留心,因为一不小心可能就破坏了原有变量的值,尤其在不理解引用的情况下,需要谨慎使用。
  PHP 中的引用很困惑
  手册上说,PHP 可以通过三种方式使用引用
  · 赋值
  · 对象赋值或者函数传递对象
  · 引用返回
  说明下,目前的 PHP 版本,对象赋值或者函数传递对象,默认就是引用方式,不用加 & 符号,其实我建议加,因为这样语言有一致性。
  重点说下引用返回,上面 Python 例子中,函数 return 返回一个变量,当实际调用的时候,函数调用赋值给一个变量,当这个变量的值改变后,函数体里面的变量值也是同步修改的。比如:
  class c(object):
  o = []
  def __init__(self, arg):
  super(c, self).__init__()
  self.arg = arg
  def r(self):
  return self.o
  obj = c(10)
  objo = obj.r()print objo
  objo.append(10)print obj.r()
  比如函数调用返回的 objo 变量(应用 c 类中的变量)值修改后,c 这个类中的实例变量 o 也会同步修改。而在 PHP 中是做不到的,比如:
  class c{
  public $o = '10';
  public function r()
  {
  return $this->o;
  }
  }
  $obj = new c;
  $objo = $obj->r();print $objo ;
  $objo = "good" ;print $obj->r();
  上面的代码 $objo 修改后,不会影响到实例的变量,可以通过引用返回解决这问题,但是语法让人觉得难以理解。
  class c{
  public $o = '10';
  public function &r()
  {
  return  $this->o;
  }
  }
  $obj = new c;
  $objo = &$obj->r();print $objo ;
  $objo = "good" ;print $obj->r();
  这里面使用两个 & 符号,函数中的 & 符号代表函数返回是个引用,第二个 & 符号表示不是赋值而是变量引用。
  总体来说,Python 中的引用和它的对象机制是一体的,而 PHP 中则是变相实现的引用。

来源:简书
0 0
原创粉丝点击