PHP和Python中的引用机制

作者: 虞大胆的叽叽喳喳 | 来源:发表于2017-04-25 19:07 被阅读287次

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 中则是变相实现的引用。

相关文章

  • PHP和Python中的引用机制

    PHP 和 Python 语言中引用是非常重要的一个概念,这个概念对于理解两门语言非常重要,会让你更深刻的认识到两...

  • PHP的面试总结

    PHP的垃圾回收机制是什么? php5和php7的垃圾回收机制都是利用引用计数。 在zval结构体中定义了ref_...

  • python学习一

    1 python 如何管理内存 对象引用计数机制,垃圾回收机制,内存池机制 一。对象引用机制 python内部引用...

  • Day11-Python垃圾回收机制笔记

    Python中的垃圾回收是以引用计数为主,标记清除和分代回收为辅。 【引用计数】 Python默认的垃圾收集机制是...

  • Python是如何进行内存管理的

    Python引入了一个机制:引用计数。 python内部使用引用计数,来保持追踪内存中的对象,Python内部记录...

  • python是如何进行内存管理的

    Python引入了一个机制:引用计数。 python内部使用引用计数,来保持追踪内存中的对象,Python内部记录...

  • python面试题(五)

    1、简述python引用计数机制(联想到垃圾回收机制)python垃圾回收主要以引用计数为主,标记-清除和分代清除...

  • 2018-09-14day20-内存管理机制

    掌握:1.数字、字符串、布尔的缓存2.垃圾回收机制中的引用计数机制 1.python中变量的赋值 python中所...

  • python 垃圾回收机制(GC)

    python 中的垃圾回收机制 Python的GC模块主要运用了“引用计数”(reference counting...

  • python爬虫面试题

    python是如何进行内存管理的? a、对象的引用计数机制 python内部使用引用计数,来保持追踪内存中的对象,...

网友评论

本文标题:PHP和Python中的引用机制

本文链接:https://www.haomeiwen.com/subject/nqfbzttx.html