ฉันจะเรียก setattr () บนโมดูลปัจจุบันได้อย่างไร


140

ฉันจะส่งผ่านสิ่งใดเป็นพารามิเตอร์แรกobjectไปยังฟังก์ชัน "" setattr(object, name, value)เพื่อตั้งค่าตัวแปรในโมดูลปัจจุบัน "

ตัวอย่างเช่น:

setattr(object, "SOME_CONSTANT", 42);

ให้ผลเช่นเดียวกับ:

SOME_CONSTANT = 42

ภายในโมดูลที่มีบรรทัดเหล่านี้ (ถูกต้องobject)

ฉันสร้างค่าหลายอย่างในระดับโมดูลแบบไดนามิกและเนื่องจากฉันไม่สามารถกำหนดได้__getattr__ที่ระดับโมดูลนี่คือทางเลือกของฉัน

คำตอบ:


220
import sys

thismodule = sys.modules[__name__]

setattr(thismodule, name, value)

หรือโดยไม่ใช้setattr(ซึ่งแบ่งจดหมายของคำถาม แต่ตอบสนองวัตถุประสงค์การปฏิบัติเดียวกัน ;-):

globals()[name] = value

หมายเหตุ : ที่ขอบเขตของโมดูลหลังจะเทียบเท่ากับ:

vars()[name] = value

ซึ่งค่อนข้างสั้นกว่า แต่ไม่สามารถใช้งานได้จากภายในฟังก์ชั่น ( vars()ให้ตัวแปรของขอบเขตที่เรียกว่า: ตัวแปรของโมดูลเมื่อเรียกที่ขอบเขตทั่วโลกและจากนั้นมันก็โอเคที่จะใช้มัน R / W แต่ฟังก์ชั่นของ ตัวแปรเมื่อมีการเรียกใช้ในฟังก์ชั่นและจากนั้นจะต้องถือว่าเป็น R / O - เอกสารออนไลน์ของ Python อาจสับสนเล็กน้อยเกี่ยวกับความแตกต่างเฉพาะนี้)


9
เอกสารให้คำเตือนเกี่ยวกับการแก้ไข vars () docs.python.org/library/functions.html#vars เมื่อไรที่จะทำเช่นนี้?
unutbu

2
@ ~ unutbu ฉันจะไม่บอกว่ามันค่อนข้าง "โอเค" แต่มันจะทำงานเมื่อคุณโทรหาvars()ที่ขอบเขตระดับโมดูลแทนที่จะอยู่ภายในฟังก์ชั่น
Mike Graham

4
vars()เทียบเท่ากับglobals()ขอบเขตของโมดูล (และส่งกลับค่า dict จริงที่ปรับเปลี่ยนได้) แต่ไปlocals()ที่ขอบเขตฟังก์ชัน (และส่งคืน pseudodict ที่ไม่เคยแก้ไข) ผมใช้vars()ในขอบเขตโมดูลตามที่บันทึก 3 ตัวอักษรหนึ่งพยางค์ VS ของคำพ้องในขอบเขตที่globals();-)
อเล็กซ์เทล

14
ใช่มันจะทำลายการปรับให้เหมาะสมที่สำคัญที่สุดอย่างเดียวที่คอมไพเลอร์ Python ทำ: ตัวแปรท้องถิ่นของฟังก์ชั่นไม่ได้ถูกเก็บไว้ใน dict พวกมันอยู่ในเวกเตอร์ที่มีค่า จำกัด และการเข้าถึงตัวแปรภายในแต่ละตัวจะใช้ดัชนีในเวกเตอร์นั้น การค้นหาชื่อ ในการเอาชนะการปรับให้เหมาะสมบังคับให้ dict ที่คุณต้องการมีอยู่เริ่มฟังก์ชันด้วยexec '': ตั้งเวลาฟังก์ชั่นที่มีลูปเป็นจำนวนมากในแต่ละวิธีและคุณจะเห็นความสำคัญของการเพิ่มประสิทธิภาพหลักนี้ต่อประสิทธิภาพของ Python
Alex Martelli

3
@msw ฉันคิดว่าคุณลืม "practicality beats purity" ;-)
Alex Martelli

6

หากคุณต้องตั้งค่าตัวแปรที่กำหนดขอบเขตของโมดูลจากภายในโมดูลจะเกิดglobalอะไรขึ้น

# my_module.py

def define_module_scoped_variables():
    global a, b, c
    a, b, c = 'a', ['b'], 3

ดังนี้:

>>> import my_module
>>> my_module.define_module_scoped_variables()
>>> a
NameError: name 'a' is not defined
>>> my_module.a
'a'
>>> my_module.b
['b']

1
ใช่ฉันเคย (ที่ "เสมอ" ถูกกำหนดให้เป็น "ไม่กี่เดือนที่ฉันได้เรียนรู้งูใหญ่") พบว่าglobal but not reallyการทำให้งงประกาศ ฉันคิดว่ามันอาจเป็นของที่ระลึกทางประวัติศาสตร์ที่มีมาก่อนเนมสเปซของโมดูล
msw

1
คำถามเดิมถามถึงวิธีการตั้งค่าแอตทริบิวต์ที่มีชื่อกำหนดโดยสตริง (สิ่งเดียวกันกับที่ฉันค้นหาในปัจจุบัน) ดังนั้นสิ่งนี้จะไม่ช่วย
Curt


-1
  1. คุณจะไม่ คุณจะทำglobals()["SOME_CONSTANT"] = 42
  2. คุณจะไม่ คุณจะเก็บเนื้อหาที่สร้างขึ้นแบบไดนามิกที่อื่นนอกเหนือจากโมดูล

ใช่SOME_CONSTANTคำนวณในเวลาทำงานไม่คงที่แน่นอน และหากคุณglobals()ไม่สามารถใช้งานได้คุณจะต้องเข้าถึงโมดูลอื่นเพื่อแก้ไขคุณสมบัติ ที่ถูกผูกไว้เพื่อให้คนสงสัย
ขยะ

3
ค่าคงที่และไม่แน่นอนจะไม่เกิดขึ้นพร้อมกัน คงที่และสร้างแบบไดนามิกไม่ได้ ค่าที่ฉันสร้างมักจะเหมือนกันเสมอและพิจารณาจาก "ค่าคงที่" เพิ่มเติมเพื่อประหยัดเลขคณิตและการพิมพ์ในส่วนของฉัน
Matt Joiner
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.