為什麼在 Python 中用參數調用這個“構造函數”?

zijuexiansheng

如果您不真正理解此代碼中發生的事情,請不要關閉此問題。這與“Least Astonishment”和可變默認參數不同

在下面的代碼中,我定義了一個clone方法,它調用不帶參數的“構造函數”。但是在該__init__方法中,參數的值不斷變化(請參閱WARNING輸出行)。這是為什麼?

代碼:

#!/usr/bin/env python3

class Foo:
    def __init__(self, aDic = {}):
        self.aDic = aDic
        print("__init__")
        if aDic:
            print("WARNING: aDic is not empty {}".format(aDic))
        self.printme()

    def printme(self):
        print("aDic = {}".format(self.aDic))

    def clone(self, props):
        print("Before calling Foo() without parameters")
        newValue = Foo()
        print("after calling Foo() without parameters")
        newValue.printme()
        print("props = {}".format(props))
        print("props.get = {}".format(props.get("aDic", self.aDic)))
        for k, v in props.get("aDic", self.aDic).items():
            newValue.aDic[k] = v
        return newValue


a = Foo(aDic = {"b": 2})
a.printme()
print()

c = a.clone({"aDic": {"b": 222}})
c.printme()
print()

a.printme()
print()

d = a.clone({"aDic": {"b": 2222}})
d.printme()
print()

輸出:

__init__
WARNING: aDic is not empty {'b': 2}
aDic = {'b': 2}
aDic = {'b': 2}

Before calling Foo() without parameters
__init__
aDic = {}
after calling Foo() without parameters
aDic = {}
props = {'aDic': {'b': 222}}
props.get = {'b': 222}
aDic = {'b': 222}

aDic = {'b': 2}

Before calling Foo() without parameters
__init__
WARNING: aDic is not empty {'b': 222}
aDic = {'b': 222}
after calling Foo() without parameters
aDic = {'b': 222}
props = {'aDic': {'b': 2222}}
props.get = {'b': 2222}
aDic = {'b': 2222}
AKX

這與“最小驚訝”和可變默認參數有關

在 中clone(),您Foo()不帶參數調用newValue.aDic參數列表中的共享字典也是如此。

然後您在內部改變該共享副本 ( newValue.aDic[k] = v),因此Foo()您從該clone()函數獲得的所有s 都將看到這些更改。

您示例的修改版本說明了這一點。看看ids 是如何相同的?

class Foo:
    def __init__(self, aDic = {}):
        self.aDic = aDic

    def printme(self):
        print(f"aDic({id(self.aDic)}) = {self.aDic}")

    def clone(self, props):
        newValue = Foo()
        newValue.printme()
        for k, v in props.get("aDic", self.aDic).items():
            newValue.aDic[k] = v
        return newValue


print("a")
a = Foo(aDic = {"b": 2})
a.printme()
print("c")
c = a.clone({"aDic": {"b": 222}})
c.printme()
print("d")
d = a.clone({"aDic": {"b": 2222}})
d.printme()

打印出來(例如)

a
aDic(4494684352) = {'b': 2}
c
aDic(4494684544) = {}
aDic(4494684544) = {'b': 222}
d
aDic(4494684544) = {'b': 222}
aDic(4494684544) = {'b': 2222}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

為什麼為第二個實例調用保留默認參數?

為什麼在 mdn 的這個示例中,每個內部函數都將先前的(父)函數參數作為輸入?

為什麼python列表佔用這麼多內存?

為什麼這個參數構造函數只適用於多行定義?

為什麼此函數在定義後立即調用時返回最後一個參數

為什麼 Python 不刪除這個字符?

這個迭代標準的名稱是什麼,它是否為 Python 實現?

為什麼這個函數只是被跳過而不是被調用?

為什麼此參數包中的函數調用會向後求值?

為什麼這些假定相同的 Python 詞典的行為不同?

為什麼在 Python 中的函數中修改了列表?

誰能告訴我為什麼這個函數在調用時會拋出錯誤

為什麼在python中沒有執行異步函數

在類中的函數調用中將“self”作為參數傳遞(Python)

為什麼調用 someMockInstance.Object 調用構造函數?

為什麼這個簡單的python函數只能工作一次

為什麼 memccpy 函數使用 int 參數?

為什麼 Redux Saga yield 調用返回一個函數,而不是數據?

為什麼移動構造函數被調用了 2 次?

Python:允許函數跨調用訪問信息的最佳結構是什麼

為什麼不調用移動構造函數?

為什麼用 | 傳遞多個值 作為 Golang 函數的參數工作?

為什麼 Python 的 yield 語句不能在一個函數中調用,也不能在它調用的另一個函數中調用,為什麼在嘗試時沒有報告錯誤?

為什麼我的代碼調用一個函數兩次?

為什麼這個自定義反向函數的行為很奇怪?

為什麼我在構造函數中填充的這個數組在構造函數返回後沒有填充?

為什麼這個模型在我定義了參數後還需要先調用'build()'?

Python:為什麼這個 if-else 代碼不正確?

為什麼我的變量只在 Python 中的某個函數/語句中發生變化?