Burada karşılaştığınız iki temel sorun var:
__xxx__
yöntemler yalnızca sınıfta aranır
TypeError: can't set attributes of built-in/extension type 'module'
(1) herhangi bir çözümün hangi modülün incelendiğini de takip etmesi gerektiği anlamına gelir, aksi takdirde her modül o zaman örnek değiştirme davranışına sahip olur; ve (2) (1) mümkün bile değil ... en azından doğrudan değil.
Neyse ki, sys.modules oraya neyin gireceği konusunda seçici değildir, bu nedenle bir sarmalayıcı çalışacaktır, ancak yalnızca modül erişimi için (yani import somemodule; somemodule.salutation('world')
; aynı modül erişimi için, yöntemleri ikame sınıfından globals()
çekmeniz ve bunları eiher'e eklemeniz gerekir. Sınıfta özel yöntem (kullanmayı seviyorum .export()
) veya genel bir işlevle (zaten yanıtlar olarak listelenenler gibi) Akılda tutulması gereken bir şey: sarmalayıcı her seferinde yeni bir örnek oluşturuyorsa ve global çözüm değilse, ince bir şekilde farklı davranışlarla sonuçlanırsınız .. Oh, ve ikisini aynı anda kullanamazsınız - biri ya da diğeri.
Güncelleme
Gönderen Guido van Rossum :
Aslında ara sıra kullanılan ve önerilen bir hack vardır: bir modül, istenen işlevselliğe sahip bir sınıfı tanımlayabilir ve ardından sonunda, kendisini sys.modules içinde bu sınıfın bir örneğiyle (veya ısrar ederseniz sınıfla değiştirebilir) , ancak bu genellikle daha az faydalıdır). Örneğin:
# module foo.py
import sys
class Foo:
def funct1(self, <args>): <code>
def funct2(self, <args>): <code>
sys.modules[__name__] = Foo()
Bu işe yarıyor çünkü içe aktarma makinesi bu hack'i aktif olarak etkinleştiriyor ve son adımı gerçek modülü yükledikten sonra sys.modules'ten çekiyor. (Bu bir tesadüf değil. Hack uzun zaman önce önerilmişti ve onu ithalat makinelerinde destekleyecek kadar sevdiğimize karar verdik.)
Dolayısıyla, istediğiniz şeyi başarmanın yerleşik yolu, modülünüzde tek bir sınıf oluşturmaktır ve modülün son eylemi olarak sys.modules[__name__]
sınıfınızın bir örneğini değiştirir - ve artık gerektiğinde __getattr__
/ __setattr__
/ ile oynayabilirsiniz __getattribute__
.
Not 1 : Bu işlevi kullanırsanız modüldeki globals, diğer işlevler vb. Gibi diğer sys.modules
her şey , atama yapıldığında kaybolacaktır - bu nedenle, gereken her şeyin yedek sınıfın içinde olduğundan emin olun.
Not 2 : Desteklemek için sınıfta tanımlamış from module import *
olmanız gerekir __all__
; Örneğin:
class Foo:
def funct1(self, <args>): <code>
def funct2(self, <args>): <code>
__all__ = list(set(vars().keys()) - {'__module__', '__qualname__'})
Python sürümünüze bağlı olarak, atlanacak başka isimler de olabilir __all__
. set()
Python 2 uyumluluğu gerekli değildir göz ardı edilebilir.