ruby 你可以在Python中的核心類型上修補補丁方法嗎?





7 Answers

你不能。 在Python中,C擴展模塊(包括內置函數)中定義的所有數據(類,方法,函數等)都是不可變的。 這是因為C模塊在同一進程中的多個解釋器之間共享,因此monkeypatching它們也會影響同一進程中不相關的解釋器。

但是,Python代碼中定義的類可能是monkeypatched,因為它們是該解釋器的本地。

python ruby programming-languages monkeypatching fluent-interface

Ruby可以向Number類和其他核心類型添加方法來獲得這樣的效果:

1.should_equal(1)

但似乎Python無法做到這一點。 這是真的? 如果是這樣,為什麼? 是否與類型無法修改的事實有關?

更新:我不想談論猴子修補的不同定義,而是只關注上面的例子。 我已經得出結論,由於你們中的一些人已經回答,所以無法完成。 但是我想要更詳細地解釋為什麼不能這樣做,也許在Python中有什麼功能允許這樣做。

回答你們中的一些人:我可能想要這樣做的原因只是美學/可讀性。

 item.price.should_equal(19.99)

這更像是英語,並清楚地表明哪個是測試值,哪個是預期值,如下所示:

should_equal(item.price, 19.99)

這個概念就是Rspec和其他一些Ruby框架所基於的。




你可以做到這一點,但它需要一點點黑客攻擊。 幸運的是,現在有一個名為“Forbidden Fruit”的模塊,它可以讓您非常簡單地修補內置類型的方法。 你可以找到它

http://clarete.github.io/forbiddenfruit/?goback=.gde_50788_member_228887816

要么

https://pypi.python.org/pypi/forbiddenfruit/0.1.0

使用原始問題示例,在您編寫“should_equal”函數之後,您就可以了

from forbiddenfruit import curse
curse(int, "should_equal", should_equal)

你很高興去! 還有一個“反向”功能來刪除修補方法。




你不能在python中修補核心類型。 但是,您可以使用管道編寫更易讀的代碼:

from pipe import *

@Pipe
def should_equal(obj, val):
    if obj==val: return True
    return False

class dummy: pass
item=dummy()
item.value=19.99

print item.value | should_equal(19.99)



如果你真的真的想在Python中做一個猴子補丁,你可以使用“import foo as bar”技術進行(sortof)hack。

如果你有一個類,如TelnetConnection,並且你想擴展它,將它子類化為一個單獨的文件,並稱之為TelnetConnectionExtended。

然後,在代碼的頂部,您通常會說:

import TelnetConnection

改變是:

import TelnetConnectionExtended as TelnetConnection

然後你的代碼中你引用的所有TelnetConnection實際上都會引用TelnetConnectionExtended。

遺憾的是,這假設您可以訪問該類,並且“as”僅在該特定文件中運行(它不是全局重命名),但我發現它不時有用。




不,你不能用Python做到這一點。 我認為這是件好事。




should_equal做什麼? 它是一個返回TrueFalse的布爾值嗎? 在這種情況下,拼寫:

item.price == 19.99

沒有考慮到品味,但沒有普通的python開發人員會說它的可讀性低於你的版本。

should_equal會設置某種驗證器嗎? (為什麼驗證器只能限制為一個值?為什麼不設置值而不在之後更新它?)如果你想要一個驗證器,這無論如何都無法工作,因為你提議修改一個特定的整數或全部整數。 (需要18.99等於19.99驗證器總是會失敗。)相反,你可以拼寫它:

item.price_should_equal(19.99)

或這個:

item.should_equal('price', 19.99)

並在item的類或超類上定義適當的方法。




這是我如何實現.should_something ...行為:

result = calculate_result('blah') # some method defined somewhere else

the(result).should.equal(42)

要么

the(result).should_NOT.equal(41)

我在一個獨立的方法中包含了一個裝飾器方法,用於在運行時擴展此行為:

@should_expectation
def be_42(self)
    self._assert(
        action=lambda: self._value == 42,
        report=lambda: "'{0}' should equal '5'.".format(self._value)
    )

result = 42

the(result).should.be_42()

你必須對內部有一些了解,但它有效。

這是來源:

https://github.com/mdwhatcott/pyspecs

它也是在pyspecs下的PyPI上。




Related