2010-05-26 9 views
7

Kabuk benzeri bir ortam oluşturuyorum. Özgün kullanıcı girdisini kullanma yöntemim, çeşitli sınıfların yöntemlerine bir sözlük eşleme komutları (dizeler) kullanmaktı ve işlevlerin python'daki birinci sınıf nesneler olduğu gerçeğini kullanmaktı.Python'un getattrını yaygın olarak kullanmak kötü bir uygulama mıdır?

Esneklik uğruna (çoğunlukla ayrıştırma komutları için), kurulumumu değiştirmeyi, getattr (komut) kullanmamı, ihtiyacım olan yöntemi almam ve sonra argümanlarıma son vermem için değiştirmeyi düşünüyorum. ayrıştırıcı. Bu yaklaşımın bir başka avantajı, her zaman yeni bir metot/komut eklediğimde (şu anda statik olarak uygulanan) komut sözlüğümü güncellemek zorunda değil.

Soruma iki kat. İlk olarak, getattr'ın aynı problemleri var mı? İkincisi, kabuğumun verimliliğine bir vuruş mu çekeceğim? Kaç tane yöntem/komut aldığım önemli mi? Şu anda iki katına çıkabilen 30 komuttan bahsediyorum.

+1

eğer http://pyparsing.wikispaces.com/ pyparsing'e bakmadınız, gerçekten de, herhangi bir şey için python'da kendi ayrıştırıcınızı yazmak için __NO__ gerçek bir sebep var. –

+2

Fuzzy, Eminim ki bir tane düşünebilirim, ve bunu benim için yapıyorum: öğrenme amaçlı. Bu mevcut projeye başlamadan önce, fonksiyonların birinci sınıf nesneler olduğu anlamlarını anlamadım. Yine de referansı takdir ediyorum. Ben ona bakacağım. "Dis check" için – Wilduck

cevap

20

Doğrudan öznitelik erişimi ile getattr() kullanımı arasındaki fark göz ardı edilebilir olmalıdır. Sen iki yaklaşımı karşılaştırmak için Python'un dis modülünü kullanarak iki sürümlerinde baytkodlarına arasındaki farkı söyleyebilir:

>>> import dis 
>>> dis.dis(lambda x: x.foo) 
    1   0 LOAD_FAST    0 (x) 
       3 LOAD_ATTR    0 (foo) 
       6 RETURN_VALUE   
>>> dis.dis(lambda x: getattr(x, 'foo')) 
    1   0 LOAD_GLOBAL    0 (getattr) 
       3 LOAD_FAST    0 (x) 
       6 LOAD_CONST    0 ('foo') 
       9 CALL_FUNCTION   2 
      12 RETURN_VALUE 

nasıl Python kütüphanesine çok benzer bir kabuk geliştiriyorlar gibi, ancak, ses yok cmd, satır kabuklarını komut dosyası yapar. cmd bunu gibi bir cmd.Cmd nesne üzerinde tanımlı bir işleve komut adını eşleştirerek komutları yürütür kabukları oluşturmanızı sağlar:

import cmd 

class EchoCmd(cmd.Cmd): 
    """Simple command processor example.""" 

    def do_echo(self, line): 
     print line 

    def do_EOF(self, line): 
     return True 

if __name__ == '__main__': 
    EchoCmd().cmdloop() 

Sen belgelere ya en modülü hakkında daha fazla okumak veya şuradan erişebilirsiniz http://www.doughellmann.com/PyMOTW/cmd/index.html

+1

+1. – EOL

+0

Bu yanıt için teşekkürler. Yukarıdaki yorumumda olduğu gibi, gerçekten bu kabukları öğrenme amacıyla yazıyorum. Gelecekte, aslında bir üretim maksadı için bir kabuk yazmam gerekirse, cmd kullanacağım. Dis hakkında bilmiyordum, referans için teşekkürler. – Wilduck

6

, getattr'ın eval ile aynı sorunlara sahip mi?

eval() no'lu kod, korumak için çok can sıkıcıdır ve ciddi güvenlik sorunları yaşayabilir. getattr(x, "foo")'u çağırmak, x.foo'u yazmanın başka bir yoludur.

benim kabuk

O belli belirsiz komut bulunmazsa yavaş ama önemli yetmez olacak verimliliğine darbeden edilecektir. Sadece on binlerce girişle kıyaslama yaparsanız bunu fark edersiniz.