最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python黑魔法之參數(shù)傳遞

 更新時(shí)間:2016年02月12日 18:22:34   作者:icedoom  
這篇文章主要介紹了python黑魔法之參數(shù)傳遞,分析了python參數(shù)傳遞的方法,感興趣的小伙伴們可以參考一下

我們都聽說,python世界里面,萬物皆對象。
怎么說萬物皆對象呢?最常見的:

> class A: pass
> a = A()

我們說a是一個(gè)對象。
那么既然是萬物了,其實(shí)A也是對象。3 也是對象。True 也是對象。"hello" 也是對象。
> def Func(): pass
o~yee, Func 也是對象。
那么對象之間的傳遞是如何呢?我們看看下面兩個(gè)簡單的例子:

> a = 3
> b = a
> b = 3 + 1
> print b
4
> print a
3

> a = []
> b = a
> b.append(1)

> print a
[1]
> print b
[1]

不是都說python所有對象都是引用傳遞嗎?為毛第一個(gè)b不是3?
好吧。事實(shí)是,在python的實(shí)現(xiàn)上,對象分為mutable 和 immutable。
這里說的對象分類,是說在實(shí)現(xiàn)上具備這樣的特性。而非對象本身的屬性。
什么是immutable?表示對象本身不可改變。這里先記住一點(diǎn),是對象 本身 不可改變。
什么叫做對象本身不可改變呢?
一個(gè)簡單的例子:

> a = (1,2,3)
> a[0] = 10  

TypeError: 'tuple' object does not support item assignment
元組的元素在初始化后就不能再被改變。也就是說,元組對象具備immutable的特性。
那么很簡單,相對的,mutable 就是可變的。比如:

> a = {}
> a[0] = 10

有了上面的兩個(gè)例子,相信大家已經(jīng)有了基本的認(rèn)識。
那么,在python世界中,哪些是具備immutable特性,哪些又是mutable的呢?
簡單講,基本類型都是immutable, 而object都是mutable的。
比如說:int, float, bool, tuple 都是immutable。
再比如:dict, set, list, classinstance 都是mutable的。
那么問題來了。既然說基本類型是 immutable ,那么最上面的 b = 3 + 1 為什么不會像tuple一樣,拋異常呢?
原因在于,int 對+操作會執(zhí)行自己的__add__方法。而__add__方法會返回一個(gè)新的對象。
事實(shí)是,當(dāng)基本類型被改變時(shí),并不是改變其自身,而是創(chuàng)建了一個(gè)新的對象。最終返回的是新的對象的引用。
怎么證明?
我們可以使用一個(gè)叫做id()的函數(shù)。該函數(shù)會返回對象的一個(gè)唯一id(目前的實(shí)現(xiàn)可以間接理解為對象的內(nèi)存地址)。
那么我們看下:

> a = 3
> id(a)
140248135804168

> id(3)
140248135804168

> id(4)
140248135804144

> a = a + 1
> id(a)
140248135804144

you see ? 當(dāng)我們執(zhí)行a=a+1 后,id(a) 已經(jīng)改變了。
深究一點(diǎn),為什么會這樣呢?
其實(shí),a = a + 1 經(jīng)歷了兩個(gè)過程:

  • 1、a + 1
  • 2、a 賦值

第2步只是一個(gè)引用的改變。重點(diǎn)在第1步。a + 1,那么python實(shí)際上會調(diào)用a.__add__(1)。
對于int類型__add__函數(shù)的實(shí)現(xiàn)邏輯,是創(chuàng)建了一個(gè)新的int對象,并返回。
不知道細(xì)心的你有沒有發(fā)現(xiàn)一個(gè)特別的地方?
id(4)的值等于id(3+1) 。這個(gè)只是python對int,和bool做的特殊優(yōu)化。不要以為其他基本類型只要值一樣都會指向相同的對象。
有個(gè)特殊的例子,str。做個(gè)簡單的實(shí)驗(yàn):

> a = "hello"
> id(a)
4365413232
> b = "hell"
> id(b)
4365386208

> id(a[:-1])
4365410928
> id(a[:-1])
4365413760

看到了嗎?雖然值相同,但是還是指向(創(chuàng)建)了不同的對象,尤其是最后兩句,哪怕執(zhí)行相同的操作,依然創(chuàng)建了不同的對象。
python這么傻,每次都創(chuàng)建新的對象?
no no no 他只是緩存了“一些”結(jié)果。我們可以再試試看:

> a = "hello"
> ret = set()
> for i in range(1000):
  ret.add(id(a[:-1]))
> print ret
{4388133312, 4388204640}

看到了嗎?python還是挺聰明的。不過具體的緩存機(jī)制我沒有深究過,期望有同學(xué)能分享下。
再次回到我們的主題,python中參數(shù)是如何傳遞的?
答案是,引用傳遞。
平時(shí)使用靜態(tài)語言的同學(xué)(比如我),可能會用下面的例子挑戰(zhàn)我了:

def fun(data):
  data = 3

a = 100
func(a)

print a # 100

不是尼瑪引用傳遞嗎?為毛在執(zhí)行func(a)后,a 的值沒有改變呢?這里犯了一個(gè)動態(tài)語言基本的錯(cuò)誤。
data=3,語義上是動態(tài)語言的賦值語句。千萬不要和C++之類的語言一個(gè)理解。
看看我們傳入一個(gè)mutable 的對象:

> def func(m):
  m[3] = 100

> a = {}
> print a
{}
> func(a)
> print a
{3:100}

現(xiàn)在同學(xué)們知道該如何進(jìn)行參數(shù)傳遞了吧?好嘞,進(jìn)階!
像很多語言如C++,js,swift... 一樣,python 的函數(shù)聲明支持默認(rèn)參數(shù):
def func(a=[]): pass
不知道什么意思?自己看書去!
我這里要說的是,如果我們的默認(rèn)參數(shù)是mutable類型的對象,會有什么黑魔法產(chǎn)產(chǎn)生?
我們看看下面的函數(shù):

def func(a=[]):
  a.append(3)
  return a

可能有同學(xué)會說了:我去!這么簡單?來騙代碼的吧?
但是,真的這么簡單嗎?我們看下下面的調(diào)用結(jié)果:

> print func()
[3]
> print func()
[3,3]
> print func()
[3,3,3]

這真的是你想要的結(jié)果嗎?
No,我要的是[3],[3],[3]!
原因?好吧,我們再用下id()神奇看看:

def func(a=[]):
  print id(a)
  a.append(3)
  return a

> print func()
4365426272
[3]
> print func()
4365426272
[3, 3]
> print func()
4365426272
[3, 3, 3]

明白沒?原來在python中,*默認(rèn)參數(shù)不是每次執(zhí)行時(shí)都創(chuàng)建的!*
這下你再想想,曾經(jīng)嘲笑過的代碼(至少我)為什么要 多此一舉:

def func(a=None):
  if a is None:
    a = []

這里在順帶提一下==, is:
== : 值比較
is : 比較左右兩邊是否是同一個(gè)對象。 a is b ==> id(a) == id(b)
ok, let's move on!
我們都知道,在python中,不定參數(shù)我們可以這樣定義:
def func(*args, **kv): pass
什么你不知道?看書去!
那args和kv到底是什么情況呢?到底是mutable 還是 immutable 呢?
再一次請出id()神器:

def func(*args):
  print id(args)


> a = [1,2]
> print id(a)
4364874816
> func(*a)
4364698832
> func(*a)
4364701496

看到了吧?實(shí)際上args也會產(chǎn)生一個(gè)新的對象。但是值是填入的傳入?yún)?shù)。那么每一個(gè)item也會復(fù)制嗎?
我們再看看:

def func(*args):
  print id(args[0])

> a = [1,2]
> print id(a[0])
140248135804216
> func(*a)
140248135804216

答案是,No。值會像普通list賦值一樣,指向原先list(a)所引用的對象。
那么為什么會這樣呢?
python的源碼就是這么寫的.......
最最后,還記得我說過的一句話嗎?
immutable 限制的是對象本身不可變
意思就是說,對象的immtable 只是限制自身的屬性能否被改變,而不會影響到其引用的對象。
看下下面的例子:

> a = [1,2]
> b = (a,3)
> b[1] = 100
TypeError: 'tuple' object does not support item assignment

> print b
([1, 2], 3)
> b[0][0] = 10
> print b
([10, 2], 3)

最最最后,我有個(gè)對象,它本身應(yīng)該是 mutable 的,但是我想讓他具備類似immutable的特性,可以嗎?
答案是,可以模擬!
還是之前說的,immutable 限制的是其自身屬性不能改變。
那么,我們的可以通過重定義(重載)屬性改變函數(shù),來模擬immutable特性。
python可以嗎?O~Yee
在python的類函數(shù)中,有這樣的兩個(gè)函數(shù): __setattr__ 和 __delattr__。分別會在對象屬性賦值和刪除時(shí)執(zhí)行。
那么我們可以進(jìn)行簡單重載來模擬immutable:

class A:
  def __setattr__(self, name, val):
    raise TypeError("immutable object could not set attr")

以上就是為大家介紹的python黑魔法,希望對大家的學(xué)習(xí)有所幫助。

相關(guān)文章

  • python uuid生成唯一id或str的最簡單案例

    python uuid生成唯一id或str的最簡單案例

    這篇文章主要介紹了python uuid生成唯一id或str的最簡單案例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • Python中運(yùn)維神器Psutil的用法詳解

    Python中運(yùn)維神器Psutil的用法詳解

    Python的開源庫psutil為我們提供了一個(gè)強(qiáng)大的工具,能夠輕松獲取和分析系統(tǒng)利用率的信息,下面就跟隨小編一起深入了解一下它的具體使用吧
    2025-02-02
  • Python全局變量操作詳解

    Python全局變量操作詳解

    這篇文章主要介紹了Python全局變量操作詳解,本文總結(jié)了兩種使用全局變量的方式,需要的朋友可以參考下
    2015-04-04
  • django 前端頁面如何實(shí)現(xiàn)顯示前N條數(shù)據(jù)

    django 前端頁面如何實(shí)現(xiàn)顯示前N條數(shù)據(jù)

    這篇文章主要介紹了django 前端頁面如何實(shí)現(xiàn)顯示前N條數(shù)據(jù)。具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • Python實(shí)現(xiàn)矩陣運(yùn)算的方法代碼實(shí)例

    Python實(shí)現(xiàn)矩陣運(yùn)算的方法代碼實(shí)例

    這篇文章主要介紹了Python實(shí)現(xiàn)矩陣運(yùn)算的方法代碼實(shí)例,想用python實(shí)現(xiàn)一個(gè)矩陣類,它可以像matlab或者numpy中的矩陣一樣進(jìn)行運(yùn)算,生成一個(gè)矩陣類Matrix之后,他接收一個(gè)二維列表作為輸入,然后將對應(yīng)的值寫到矩陣對應(yīng)的位置,需要的朋友可以參考下
    2023-08-08
  • Python使用scrapy爬取陽光熱線問政平臺過程解析

    Python使用scrapy爬取陽光熱線問政平臺過程解析

    這篇文章主要介紹了Python使用scrapy爬取陽光熱線問政平臺過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-08-08
  • django創(chuàng)建自定義模板處理器的實(shí)例詳解

    django創(chuàng)建自定義模板處理器的實(shí)例詳解

    這篇文章主要介紹了django創(chuàng)建自定義模板處理器的實(shí)例詳解的相關(guān)資料,這里說明了如何需要django模板處理器及實(shí)現(xiàn)方法,希望大家能理解掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-08-08
  • python中Tkinter詳細(xì)基礎(chǔ)教學(xué)實(shí)例代碼

    python中Tkinter詳細(xì)基礎(chǔ)教學(xué)實(shí)例代碼

    這篇文章主要給大家介紹了關(guān)于python中Tkinter詳細(xì)基礎(chǔ)教學(xué)的相關(guān)資料,文中介紹了如Label、Button、Entry、Text、Frame、Menu、Canvas、Messagebox等的基本屬性和用法,并介紹了布局管理器pack、grid和place的使用方法,需要的朋友可以參考下
    2024-12-12
  • Python中@符號的用法小結(jié)

    Python中@符號的用法小結(jié)

    @符號在Python中最常見的使用情況是在裝飾器中,本文主要介紹了Python中@符號的用法小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • 10個(gè)Python中python_docx庫的實(shí)用案例分享

    10個(gè)Python中python_docx庫的實(shí)用案例分享

    在日常辦公和文檔處理中,Word文檔是我們最常用的格式之一,Python通過python?-?docx庫能夠?qū)崿F(xiàn)對Word文檔的各種自動化操作,本文為大家準(zhǔn)備了10個(gè)常用的案例,希望對大家有所幫助
    2025-02-02

最新評論

呼玛县| 施甸县| 合江县| 泾川县| 潼关县| 临海市| 芜湖县| 桐乡市| 库尔勒市| 衡阳市| 苗栗县| 平舆县| 庆云县| 芜湖县| 潢川县| 额敏县| 清涧县| 尚义县| 嘉黎县| 驻马店市| 永昌县| 治多县| SHOW| 绵阳市| 绿春县| 湖口县| 龙山县| 迭部县| 凌海市| 鹤岗市| 东丽区| 望都县| 锦州市| 峨眉山市| 广南县| 仪陇县| 阳西县| 彭山县| 兴国县| 鄂尔多斯市| 将乐县|