Maymun yaması nedir?


548

Anlamaya çalışıyorum, maymun yaması ya da maymun yaması nedir?

Aşırı yükleme veya yetkilendirme yöntemleri / operatörleri gibi bir şey mi?

Bu şeylerle ortak bir yanı var mı?


Bence Google tanımı yararlı ve en genel:Monkey patching is a technique to add, modify, or suppress the default behavior of a piece of code at runtime without changing its original source code.
Charlie Parker

Yanıtlar:


522

Hayır, bunların hiçbirine benzemiyor. Basitçe, çalışma zamanında özelliklerin dinamik olarak değiştirilmesi.

Örneğin, yöntemi olan bir sınıfı düşünün get_data. Bu yöntem harici bir arama yapar (örneğin bir veritabanında veya web API'sinde) ve sınıftaki diğer çeşitli yöntemler bunu çağırır. Ancak, birim sınamasında, dış veri kaynağına bağımlı olmak istemezsiniz; böylece get_datayöntemi, sabit verileri döndüren bir saplama ile dinamik olarak değiştirirsiniz .

Python sınıfları değiştirilebilir olduğundan ve yöntemler yalnızca sınıfın öznitelikleri olduğundan, bunu istediğiniz kadar yapabilirsiniz - ve aslında, bir modüldeki sınıfları ve işlevleri tam olarak aynı şekilde değiştirebilirsiniz.

Ancak, bir yorumcunun işaret ettiği gibi, maymun derleme yaparken dikkatli olun:

  1. Test mantığınızın yanı sıra başka bir şey varsa get_data, orijinal yerine maymun yamalı değiştirme işleminizi de çağırır - ki bu iyi veya kötü olabilir. Sadece dikkat et.

  2. get_dataİşlevi değiştirdiğinizde işleve işaret eden bir değişken veya öznitelik varsa , bu diğer ad anlamını değiştirmez ve orijinali göstermeye devam eder get_data. (Neden? Python get_data, sınıfınızdaki adı başka bir işlev nesnesine yeniden hatırlatıyor ; diğer ad bağlamaları hiç etkilenmiyor.)


1
@LutzPrechelt benim için açık olmak gerekirse, ne demek istiyorsun pointing to the original get_data function? Bir değişkeni bir işlevde saklarsanız, değişkeni değiştiren bir işlev eskisini işaret etmeye devam edecek mi?
fabriciorissetto

3
@fabriciorissetto: Normalde Python'daki işlev nesnelerini değiştirmezsiniz. Maymun yaması get_datayaptığınızda, adı get_datasahte bir işleve yeniden bağlarsınız . Programda başka bir yerde başka bir isim varsa, eski adıyla bilinen fonksiyona bağlıysa get_data, o isim için hiçbir şey değişmez.
Lutz Prechelt

1
@LutzPrechelt Bununla ilgili biraz daha açıklayabilir misiniz?
Calvin Ku

Maymun yamalarının özellikle hata ayıklama için ve dekoratörler veya nesne fabrikaları işlevlerinde yararlı olabileceğini düşünüyorum. Bununla birlikte, açık bir şekilde örtülü olmaktan daha iyi olduğunu unutmayın, bu nedenle kodunuzun içeriğe duyarsız olduğundan emin olun, "Zararlı sayılır", vb.
Okuyun

Yani, sadece 'eval' işlevini kullanmaya benzer bir şey, burada çalışma zamanında yeni kod ekleyebilir misiniz?
wintermute

363

MonkeyPatch, çalışma zamanında (genellikle başlangıçta) diğer kodu genişleten veya değiştiren bir Python kodu parçasıdır.

Basit bir örnek şöyle görünür:

from SomeOtherProduct.SomeModule import SomeClass

def speak(self):
    return "ook ook eee eee eee!"

SomeClass.speak = speak

Kaynak: Zope wiki'deki MonkeyPatch sayfası.


126

Maymun yaması nedir?

Basitçe söylemek gerekirse, maymun yama, program çalışırken bir modül veya sınıfta değişiklikler yapıyor.

Kullanım örneği

Panda belgelerinde maymun yamalama örneği var:

import pandas as pd
def just_foo_cols(self):
    """Get a list of column names containing the string 'foo'

    """
    return [x for x in self.columns if 'foo' in x]

pd.DataFrame.just_foo_cols = just_foo_cols # monkey-patch the DataFrame class
df = pd.DataFrame([list(range(4))], columns=["A","foo","foozball","bar"])
df.just_foo_cols()
del pd.DataFrame.just_foo_cols # you can also remove the new method

Bunu kırmak için önce modülümüzü içe aktarıyoruz:

import pandas as pd

Daha sonra, herhangi bir sınıf tanımının kapsamı dışında sınırsız ve serbest olarak var olan bir yöntem tanımı yaratırız (çünkü bir işlev ve bağlı olmayan bir yöntem arasındaki ayrım oldukça anlamsız olduğundan, Python 3 bağlı olmayan yöntemi ortadan kaldırır):

def just_foo_cols(self):
    """Get a list of column names containing the string 'foo'

    """
    return [x for x in self.columns if 'foo' in x]

Daha sonra, bu yöntemi kullanmak istediğimiz sınıfa ekliyoruz:

pd.DataFrame.just_foo_cols = just_foo_cols # monkey-patch the DataFrame class

Ve sonra yöntemi sınıfın bir örneğinde kullanabilir ve işimiz bittiğinde yöntemi silebiliriz:

df = pd.DataFrame([list(range(4))], columns=["A","foo","foozball","bar"])
df.just_foo_cols()
del pd.DataFrame.just_foo_cols # you can also remove the new method

İsim yönetimi için uyarı

Ad yönetimi (adı değiştiren ve önermediğim çift alt çizgili önek öznitelikleri) kullanıyorsanız, bunu yaparsanız manuel olarak ad değiştirmeyi yapmanız gerekir. İsim yönetimi önermediğim için burada göstermeyeceğim.

Test Örneği

Bu bilgiyi, örneğin testlerde nasıl kullanabiliriz?

Diyelim ki bir dış veri kaynağına bir hata ile sonuçlanan bir veri alma çağrısı simüle etmemiz gerekiyor, çünkü böyle bir durumda doğru davranışı sağlamak istiyoruz. Bu davranışı sağlamak için veri yapısına maymun ekleyebiliriz. (Yani Daniel Roseman tarafından önerilen benzer bir yöntem adı kullanarak :)

import datasource

def get_data(self):
    '''monkey patch datasource.Structure with this to simulate error'''
    raise datasource.DataRetrievalError

datasource.Structure.get_data = get_data

Ve bu yöntemin bir hataya neden olan davranışı test ettiğimizde, doğru bir şekilde uygulanırsa, bu davranışı test sonuçlarında alırız.

Sadece yukarıdakileri yapmak, Structureişlemin ömrü boyunca nesneyi değiştirecektir , bu nedenle bunu yapmaktan kaçınmak için birim testlerinizde kurulum ve gözyaşı kullanmak istersiniz, örneğin:

def setUp(self):
    # retain a pointer to the actual real method:
    self.real_get_data = datasource.Structure.get_data
    # monkey patch it:
    datasource.Structure.get_data = get_data

def tearDown(self):
    # give the real method back to the Structure object:
    datasource.Structure.get_data = self.real_get_data

Yukarıdaki ince iken (muhtemelen kullanmak daha iyi bir fikir olacağını mockkodu yama kütüphane. mock'Nin patchdekoratör kod fazla satır ve hataları tanıtmak böylece daha fazla fırsat gerektirecektir yukarıda yapmaktan daha eğilimli az hata olurdu Henüz kodu incelemek zorunda mockdeğilim ama benzer bir şekilde maymun yama kullandığını hayal ediyorum.)


gerçek yönteme bir referans depolamak için maymun avcısı üzerindeki yük nedir? örneğin, bir "işaretçi tut" adımını unutursa, kaybolur?
Tommy

3
@Tommy Bir "üzerine yazılan" yönteme başvurulursa sıfıra gider - çöp toplanır ve dolayısıyla işlemin ömrü boyunca "kaybedilir" (veya kaynaklandığı modül yeniden yüklenmedikçe, ancak genellikle önerilmez).
Aaron Hall

33

Wikipedia'ya göre :

Python'da maymun yaması terimi, yalnızca bir sınıfın ya da modülün çalışma zamanında, mevcut üçüncü taraf kodunu istediğiniz gibi davranmayan bir hata ya da özelliğe geçici bir çözüm olarak düzeltme niyetiyle harekete geçirilen dinamik modifikasyonlarını ifade eder.


16

Birincisi: maymun yaması kötü bir hack'tir (bence).

Genellikle modül veya sınıf düzeyindeki bir yöntemi özel bir uygulamayla değiştirmek için kullanılır.

En yaygın usecase, orijinal kodu değiştiremediğinizde bir modül veya sınıftaki bir hata için bir geçici çözüm eklemektir. Bu durumda, "yanlış" kodu maymun yamasıyla kendi modülünüzün / paketinizin içindeki bir uygulamayla değiştirirsiniz.


8
Bazı modüllerin aynı şeyi maymunla yamalaması durumunda: mahkum olursunuz.
Andreas Jung

49
Gücü gerçekten genel olarak tehlikeli olsa da, test için harika
dkrikun

1
En yaygın kullanım alanı aslında testler, özellikle birim testler içindir. Yalnızca kodunuzu test etmek istiyorsunuz, bu nedenle beklenen bir sonucu döndürmek için herhangi bir harici aramayı yamanız gerekir.
brocoli

1
bu kötü değil, yeni bir bağımlılık oluşturmak ve yeni bir bağımlılık yaratmak yerine yeni bir sürüm çıkana kadar diğer insanların yazılımlarındaki hataları düzeltmek için kullanıyorum.
nurettin

1
Maymun yama, sadece sınıfınızın / metodunuzun yeni bir yamalı versiyonunu döndüren dekoratörler içinde yama yapmak suretiyle değişebilir, "bağlama duyarlı", goto benzeri bir şekilde değil "saf fonksiyonel bir şekilde" yapılabilir. Birçok C # / Java programcısı REPL güdümlü geliştirme hakkında bilgi sahibi değildir, bu nedenle IDE'lerinde her şeyin statik olarak tanımlanmasını gerektiren kodlar. C # / Java'da maymun yaması olmadığı için, statik IDE odaklı geliştirme uygulamalarına giderken JavaScript, Smalltalk, Lisp, Python vb.
aoeu256

13

Maymun yaması sadece python'un iyi bir örnek olduğu dinamik dillerde yapılabilir. Nesne tanımını güncellemek yerine çalışma zamanında bir yöntemi değiştirmek buna bir örnektir; benzer şekilde, çalışma zamanında öznitelikler (yöntemler veya değişkenler olsun) eklemek maymun düzeltme eki olarak kabul edilir. Bunlar genellikle kaynağınız olmayan modüller ile çalışırken, nesne tanımlarının kolayca değiştirilemeyeceği şekilde yapılır.

Bu kötü olarak kabul edilir, çünkü bir nesnenin tanımının gerçekte nasıl davrandığını tamamen veya doğru bir şekilde tarif etmediği anlamına gelir.


Bununla birlikte, maymun yama, mevcut bir nesneyi veya sınıfı değiştirmek yerine, "sizi im yamalayacağım" diye çığlık atan bir dekoratör içindeki üyelere yamalanmış bir nesnenin yeni bir versiyonunu oluşturduğunuz sürece yararlı olabilir.
aoeu256

Düzeltme eklerinin yamalara yapıştırmak için kullanıldığı yamalı üyeye depolamak için yamalı üyelerdeki ek açıklamaları kullanabilirsiniz. Diyelim ki geri alma yöntemiyle bir işlev nesnesinin yeni bir geri alınamaz sürümünü oluşturan geri alınabilir bir dekoratörünüz var. Dekoratöre, geri alınamaz dekoratörünüze işaret eden bir yamalı alan koyabilirsiniz.
aoeu256

5

Maymun yaması, çalışma zamanında sınıftaki mevcut sınıfları veya yöntemleri yeniden açar ve dikkatli bir şekilde kullanılması gereken davranışı değiştirir veya yalnızca gerçekten ihtiyacınız olduğunda kullanmalısınız.

Python dinamik bir programlama dili olduğundan, Sınıflar değiştirilebilir, böylece bunları yeniden açabilir ve değiştirebilir, hatta değiştirebilirsiniz.


1

Maymun yaması nedir? Maymun yama, çalışma sırasında bir kod parçasının davranışını dinamik olarak güncellemek için kullanılan bir tekniktir.

Neden maymun yama kullanmalı? Kaynak kodunu gerçekten değiştirmeden çalışma zamanında kitaplıkların, modüllerin, sınıfların veya yöntemlerin davranışını değiştirmemize veya genişletmemize olanak tanır

Sonuç Maymun yaması harika bir teknik ve şimdi bunu Python'da nasıl yapacağımızı öğrendik. Ancak, tartıştığımız gibi, kendi dezavantajları vardır ve dikkatle kullanılmalıdır.

Daha fazla bilgi için lütfen [1] 'e başvurun: https://medium.com/@nagillavenkatesh1234/monkey-patching-in-python-explained-with-examples-25eed0aea505

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.