PHP和Python中的引用机制

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容