2009-05-19 4 views
69

, ben böyleCan modülleri, nesnelerin yapabileceği özelliklere sahip olabilir mi? piton özellikleri ile

obj.y 

sadece bir değeri dönen yerine bir işlevini çağırır olduğunu yapabilirsiniz.

Modüllerle bunu yapmanın bir yolu var mı? Ben

module.y 

sadece orada saklanan değeri dönen yerine, bir işlevi çağırmak istediğiniz bir durum var.

+2

Tekabül eden bir işlev çağırmakla ilgili sorun nedir? –

+8

, çok şey yapan bazı şeyleri daha az yazarak yapmak ister. –

cevap

50

Yalnızca yeni stil sınıflarının örneklerinin özellikleri olabilir. Python'un böyle bir örneğin, sys.modules[thename] = theinstance'da saklayarak bir modül olduğuna inanmasını sağlayabilirsiniz. Yani, örneğin, m.py modül dosya olabilir:

import sys 
class _M(object): 
    def __init__(self): 
    self.c = 0 
    def afunction(self): 
    self.c += 1 
    return self.c 
    y = property(afunction) 
sys.modules[__name__] = _M() 

Düzenlendi: globaller karşı zımni bağımlılık kaldırıldı (örnek noktası ile ilgisi yoktu ama yaparak şeyler karıştırmayın yaptılar orijinal kod başarısız!).

+0

Bunu yapmayı hiç düşünmemiştim. Kabul etmem olası değil, ama asla bilemezsiniz. Python'da keşfedilmemiş caddeler hakkında her zaman mutlu olduğun için teşekkürler. –

+1

Bunu başka hiç kimse denedi mi? Bu kodu x.py bir dosyaya koyup diğerinden içe aktardığımda, xy sonuçlarının AttributeError içinde çağrılması: 'NoneType' nesnesinin 'c' özelliği yoktur, çünkü _M bir şekilde değeri yoktur ... – Stephan202

+0

Bir şey yanlış yazıyor olmalısınız . $ python ... >>> import sys >>> sınıf _M (nesne): ... c = 0 ... def aProgram (öz): interaktif bir oturumu kontrol ... _M .c + = 1 ... dönüş _M.c ... y = özellik (işlem yok) ... >>> sys.modüller [ 'bowwow'] = _M() bowwow >>> import >>> bowwow.y >>> bowwow.y 2 >>> ... beklenen tam olarak, tabii ki. Peki, tam olarak ne yaptığınız farklı? –

44

düzgün bir modülün tüm özelliklerini miras için bu yapacağını ve doğru isinstance()

import types 

class MyModule(types.ModuleType): 
    @property 
    def y(self): 
     return 5 


>>> a=MyModule("test") 
>>> a 
<module 'test' (built-in)> 
>>> a.y 
5 

tanımlanabilir Ve sonra sys.modules içine bu ekleyebilirsiniz:

sys.modules[__name__] = MyModule(__name__) # remember to instantiate the class 
+0

Bu, yalnızca en basit durumlar için çalışıyor gibi görünüyor. Olası sorunlar şunlardır: (1) bazı ithalat yardımcıları, manuel olarak tanımlanması gereken "__file__" gibi başka özellikler de bekleyebilirler, (2) sınıfı içeren modülde yapılan ithalatlar, çalışma süresi boyunca "görünür" olmayacaktır. – tutuDajuju

+1

'types.ModuleType'dan bir alt sınıf türetmek gerekli değil, _any_ (new-style) sınıfı yapacak. Tam olarak hangi özel modül özellikleri devralmayı umuyorsunuz? – martineau

+0

Orijinal modül bir paket ise ve orijinal modülün altındaki modüllere erişmek istiyorsam ne olur? –

1

Tipik kullanım durumu: bazı (az) dinamik özniteliklerle (büyük) mevcut bir modülü zenginleştirme - tüm modül öğelerini sınıf düzenine çevirmeden. sys.modules[__name__].__class__ = MyPropertyModule gibi en basit bir modül sınıfı yama, TypeError: __class__ assignment: only for heap types ile başarısız oluyor. Böylece modül oluşturma işleminin yeniden yapılması gerekir.

# propertymodule.py 
""" Module property example """ 

if '__orgmod__' not in globals(): 

    # constant prolog for having module properties/supports reload() 

    print "PropertyModule stub execution", __name__ 
    import sys, types 
    class PropertyModule(types.ModuleType): 
     def __str__(self): 
      return "<PropertyModule %r from %r>" % (self.__name__, self.__file__) 
    modnew = PropertyModule(__name__, __doc__) 
    modnew.__modclass__ = PropertyModule   
    modnew.__file__ = __file__ 
    modnew.__orgmod__ = sys.modules[__name__] 
    sys.modules[__name__] = modnew 
    exec sys._getframe().f_code in modnew.__dict__ 

else: 

    # normal module code (usually vast) .. 

    print "regular module execution" 
    a = 7 

    def get_dynval(module): 
     return "property function returns %s in module %r" % (a * 4, module.__name__)  
    __modclass__.dynval = property(get_dynval) 

Kullanımı:

>>> import propertymodule 
PropertyModule stub execution propertymodule 
regular module execution 
>>> propertymodule.dynval 
"property function returns 28 in module 'propertymodule'" 
>>> reload(propertymodule) # AFTER EDITS 
regular module execution 
<module 'propertymodule' from 'propertymodule.pyc'> 
>>> propertymodule.dynval 
"property function returns 36 in module 'propertymodule'" 

Not: from propertymodule import dynval gibi bir şey donmuş üretecek

Bu yaklaşım sadece modül kodunun üzerine bazı prolog alarak, Python ithalat kanca olmadan yapıyor kursun kopyası - dynval = someobject.dynval

İlgili konular