2011-07-27 18 views
10

Geçtiğimiz günlerde Python öğreniyorum ve mükemmel çalışma zamanı meta programlama yeteneklerine hayran kaldım. Daha önce “runtime metaprogramming” terimiyle karşılaştım ve en iyi runtime metaprogramlama özelliklerine sahip olduğumu bildiğim kadarıyla Smalltalk hakkında okuduğum zamandı. Python Smalltalk w.r.t. metaprogramming? İki dilin yaklaşımları arasındaki farklar nelerdir?Python ve Smalltalk - Meta programlayabilme yetenekleri karşılaştırma

+0

Python'da, türleri ve callables türleri birinci sınıftır ve bunları oluşturmak veya hatta çalışma zamanında oluşturmak makul olur. Bundan daha büyülü olan herhangi bir şey genellikle "pythonic" * olarak düşünülür. DSL'leri python'da yaratmayı sevmiyoruz, sadece python kullanıyoruz. – SingleNegationElimination

+0

@TokenMacGuy: Cevabınız için teşekkürler! Benim sorum, metaprogramlamanın Pythonic olup olmadığı ya da yapıp yapmaması gerektiği ile ilgili değildir. Bu, iki dilin metaprogramlama yeteneklerinin karşılaştırmalı çalışmasına ilişkin basit bir akademik sorudur. – missingfaktor

+3

Smalltalk'un büyük fikirlerinden biri ortogonalitedir. Frankly Python bu konuda ıstırap çekiyor. Her şey her şeyde işe yaramaz. Örnekler: inspect.getargspec(), yerleşik işlevler üzerinde çalışmaz (yine de C yorumlayıcısında). eval yalnızca ifade dizeleri için çalışır ve exec yalnızca ifade dizeleri için çalışır. Lambda ifadeleri seçilemez. Belki PyPy'nin bu sorunları yok, emin değilim. Ama ben Python'u çok seviyorum ve metaclass'ları, körlemeyi ve gerçek uygulamalardaki ara sıra tanımlayıcıyı kullanmak için çok uygun buluyorum. – wberry

cevap

12

Python aslında burada oldukça iyi durumda. Smalltalk genellikle program ile meta program arasında belirgin bir ayrım yapmaz, ancak Python daha açıktır - örneğin, dekoratörler için özel sözdizimi veya metaprogramlama kancaları için __foo__() adlandırma kuralı. Bu iyi birşey. Diğer taraftan, bir elma-portakal karşılaştırması birazdır. Smalltalk, Python'dan daha küçük, daha sıkı bir dildir ve metaprogramlarla işlemek için daha az malzeme vardır. Örneğin, __getattr__()'u düşünün. Bu, Python nesnelerine özel erişim erişimi uygulaması sağlayan bir kancadır. Smalltalk'ın böyle bir şeyi yok. Fakat! Smalltalk, bir nesnenin dahili halinin daha sıkı bir şekilde kapsüllenmesini zorlar ve Python'da kullanılan object.attribute sözdiziminin eşdeğeri yoktur. Yani bir nesnenin durumunu okumak, bir yöntemin içinden geçmeyi gerektirir ... bu da tam olarak __getattr__()'un sağladığı şeydir. Dolayısıyla, Python'da __getattr__()'u kullandığınız birçok durumda, Smalltalk'ta normal bir yöntem yazmanız yeterlidir; meta programlamaya gerek yoktur.

Ve bu her yerde olduğu gibi: Python'un __getitem__() ve arkadaşları, listeleri veya sözlükleri taklit eden sınıflar yazmayı mümkün kılıyor. Smalltalk buna ihtiyaç duymaz çünkü Array ve Dictionary sadece normal Smalltalk sınıflarıdır ve bunları kullanmak için özel bir sözdizimi yoktur. Python __eq__() ve benzeri operatör aşırı yüklenmesini etkinleştirin. Smalltalk'ın operatörleri yoktur, bu yüzden özel bir şey yapmadan +'u uygulayabilirsiniz. Python'un contextlib, kendi içerik yöneticilerinizi uygulamak için bazı şık araçlar sağlar. Smalltalk, with yapısına sahip değildir, ancak lambdalar için gerçekten hafif bir sözdizimine sahiptir, bu da aynı şeyi basit bir şekilde yapmanızı sağlar. Smalltalk'ın metaprogramlama tesisleri oldukça düşük seviyeli olma eğilimindedir. Örneğin, kendi CompiledMethod örneklerinizi oluşturabilir ve bunları bir sınıfın yöntem sözlüğüne yapıştırabilirsiniz. Kendi derleyicinizi de yazabilir ve belirli bir sınıfın tüm yöntemlerinin bununla birlikte derlenmesini sağlayabilirsiniz. Bu, her türlü şeye olanak sağlar - alternatif sözdizimleri ile deneyler yapan projeler gördüm, profil oluşturma için araç bayt kodu, tuzak okumaları ve şeffaf kalıcılık için örnek değişkenlere yazma vb.

Smalltalk'ın metaprogramlama olanakları güçlüdür, ancak Python'unki gibi düzgün bir şekilde organize edilmezler ve sık sık kullanılmazlar.

10

Soruların yanıtında bir yanıt olarak gönderildi. Smalltalk'ın büyük fikirlerinden biri ortogonalitedir. Frankly Python bu konuda ıstırap çekiyor. Her şey her şeyde işe yaramaz. Örnekler:

  • inspect.getargspec()

    (yine C tercüman olarak) yerleşik işlevleri veya functools.partial çağrı sonuçlarını çalışmaz.
  • eval yalnızca ifade dizeleri için çalışır ve exec yalnızca ifade dizeleri için çalışır.
  • Lambda ifadeleri seçilemez.
  • myclass = type('x', (object,), {'__init__': partial(foo, value)}), örneklenemeyen bir sınıf üretir, buna karşılık partial yerine eşdeğer lambda ifadesi geçiyor. (Bu bir özellik değil, bir hata olabilir.)

Belki PyPy'nin bu sorunları yok, emin değilim. Ama ben Python'u çok seviyorum ve metaclass'ları, körlemeyi ve gerçek uygulamalardaki ara sıra tanımlayıcıyı kullanmak için çok uygun buluyorum.

+1

C ve Python işlevleri arasında bir çok farklılıklar PyPy'de gerçekten kaldırılmıştır (gerçekten bunları davranışlarla ayıramazsınız). dekapaj kısıtlamaları kalır (sadece pikap çılgın olduğu için) – fijal

+0

@fijal: Asitleme konusunda o kadar çılgınlık var? – missingfaktor

+1

Turşu, tüm fonksiyonları ve sınıfları isme göre referans gösteren global duruma dayanır. Bir örnek için etrafına çalışmak için NamedTuple crazy sys._getframe hacks bakın. Küresel isminde lambda'nın ismine göre başvuruda bulunamazsınız, bu yüzden onları seçemezsiniz (bu nasıl dizayn edildi ve PyPy'de de aynı şekilde çalışır) – fijal