มีปัญหาพื้นฐานสองประการที่คุณพบที่นี่:
__xxx__
วิธีการจะถูกค้นหาในชั้นเรียนเท่านั้น
TypeError: can't set attributes of built-in/extension type 'module'
(1) หมายถึงวิธีการแก้ปัญหาใด ๆ ที่จะต้องติดตามด้วยว่าโมดูลใดถูกตรวจสอบมิฉะนั้นทุกโมดูลจะมีพฤติกรรมการแทนที่อินสแตนซ์ และ (2) หมายความว่า (1) เป็นไปไม่ได้ด้วยซ้ำ ... อย่างน้อยก็ไม่ใช่โดยตรง
โชคดีที่ sys.modules ไม่จู้จี้จุกจิกเกี่ยวกับสิ่งที่ไปที่นั่นดังนั้น wrapper จะใช้งานได้ แต่สำหรับการเข้าถึงโมดูลเท่านั้น (เช่นimport somemodule; somemodule.salutation('world')
สำหรับการเข้าถึงโมดูลเดียวกันคุณต้องดึงวิธีการจากคลาสการทดแทนและเพิ่มลงในglobals()
eiher ด้วย a วิธีการที่กำหนดเองในคลาส (ฉันชอบใช้.export()
) หรือกับฟังก์ชันทั่วไป (เช่นที่ระบุไว้แล้วเป็นคำตอบ) สิ่งหนึ่งที่ควรคำนึงถึง: หาก Wrapper กำลังสร้างอินสแตนซ์ใหม่ทุกครั้งและโซลูชัน globals ไม่ใช่ คุณจบลงด้วยพฤติกรรมที่แตกต่างกันอย่างละเอียดโอ้และคุณไม่ได้ใช้ทั้งสองอย่างพร้อมกันไม่ว่าจะเป็นอย่างใดอย่างหนึ่ง
ปรับปรุง
จากGuido van Rossum :
มีการแฮ็กที่ใช้และแนะนำเป็นครั้งคราว: โมดูลสามารถกำหนดคลาสที่มีฟังก์ชันการทำงานที่ต้องการจากนั้นในตอนท้ายให้แทนที่ตัวเองใน sys.modules ด้วยอินสแตนซ์ของคลาสนั้น (หรือด้วยคลาสหากคุณยืนยัน แต่โดยทั่วไปมีประโยชน์น้อยกว่า) เช่น:
# module foo.py
import sys
class Foo:
def funct1(self, <args>): <code>
def funct2(self, <args>): <code>
sys.modules[__name__] = Foo()
สิ่งนี้ใช้ได้ผลเนื่องจากเครื่องจักรนำเข้ากำลังเปิดใช้งานการแฮ็กนี้และเมื่อขั้นตอนสุดท้ายดึงโมดูลจริงออกจากระบบโมดูลหลังจากโหลด (นี่ไม่ใช่อุบัติเหตุการแฮ็กถูกเสนอมานานแล้วและเราตัดสินใจว่าเราชอบมากพอที่จะสนับสนุนมันในเครื่องจักรนำเข้า
ดังนั้นวิธีที่กำหนดไว้ในการบรรลุสิ่งที่คุณต้องการคือการสร้างคลาสเดียวในโมดูลของคุณและเมื่อการกระทำสุดท้ายของโมดูลแทนที่sys.modules[__name__]
ด้วยอินสแตนซ์ของคลาสของคุณ - และตอนนี้คุณสามารถเล่นกับ__getattr__
/ __setattr__
/ ได้__getattribute__
ตามต้องการ
หมายเหตุ 1 : หากคุณใช้ฟังก์ชันนี้สิ่งอื่นใดในโมดูลเช่นลูกโลกฟังก์ชันอื่น ๆ ฯลฯ จะสูญหายไปเมื่อทำการsys.modules
มอบหมายงานดังนั้นโปรดตรวจสอบให้แน่ใจว่าทุกสิ่งที่จำเป็นอยู่ในคลาสทดแทน
หมายเหตุ 2 : เพื่อสนับสนุนfrom module import *
คุณต้อง__all__
กำหนดไว้ในคลาส ตัวอย่างเช่น:
class Foo:
def funct1(self, <args>): <code>
def funct2(self, <args>): <code>
__all__ = list(set(vars().keys()) - {'__module__', '__qualname__'})
ทั้งนี้ขึ้นอยู่กับรุ่นหลามของคุณอาจจะมีชื่ออื่น ๆ __all__
ที่จะละเว้นจาก set()
สามารถละเว้นถ้างูหลาม 2 เข้ากันได้ไม่จำเป็นต้อง