Geçerli modülde setattr () öğesini nasıl çağırırım?


140

Geçerli modüldeki değişkenleri ayarlamak objectiçin işleve ilk parametre " " olarak ne setattr(object, name, value)iletirim?

Örneğin:

setattr(object, "SOME_CONSTANT", 42);

aynı etkiyi vererek:

SOME_CONSTANT = 42

bu satırları içeren modül içinde (doğru object).

Dinamik olarak modül düzeyinde birkaç değer üretiyorum ve modül düzeyinde tanımlayamadığım __getattr__için bu benim yedekim.

Yanıtlar:


220
import sys

thismodule = sys.modules[__name__]

setattr(thismodule, name, value)

veya kullanmadan setattr(sorunun mektubunu kırar, ancak aynı pratik amaçları karşılar ;-):

globals()[name] = value

Not : modül kapsamında, ikincisi şuna eşittir:

vars()[name] = value

bu biraz daha özlüdür, ancak bir işlev içinde çalışmaz ( vars()çağrıldığı kapsamın değişkenlerini verir: modülün global kapsamda çağrıldığında değişkenleri verir ve sonra R / W kullanmakta sorun yoktur, ancak işlev değişkenler bir işlevde çağrıldığında ve sonra R / O olarak ele alınmalıdır - Python çevrimiçi dokümanları bu özel ayrım hakkında biraz kafa karıştırıcı olabilir).


9
Dokümanlar vars () 'i değiştirme hakkında bir uyarı verir. docs.python.org/library/functions.html#vars . Bunu ne zaman yapabilirim?
unutbu

2
@ ~ unutbu, gerçekten "tamam" olduğunu söyleyemem, ama vars()bir fonksiyonun içinde değil, modül düzeyinde bir kapsamda aradığınızda işe yarayacaktır .
Mike Graham

4
vars()globals()modül kapsamı ile eşdeğerdir (ve bu nedenle gerçek, değiştirilebilir bir dikte döndürür) ancak locals()işlev kapsamı ile eşdeğerdir (ve hiçbir zaman değiştirilmeyecek bir sahte kod döndürür). vars()Modül kapsamında kullanıyorum , bir karakter heceli 3 karakter, yani o kapsamdaki eş anlamlısı globals();-)
Alex Martelli

14
Bir işlevin yerel değişkenler gibidir: Evet, Python derleyici yapar tek ve en önemli optimizasyonu yok ederdi değil , bunlar değerlerin sıkı bir vektör dahil olduğunuz bir dict tutulur ve her bir yerel değişken erişimi, o vektör içinde indeksi kullanır bir isim araması. Optimizasyonu yenmek, var olmasını istediğiniz zorlamayı zorlamak için, işleve şu şekilde başlayın exec '': her iki önemli döngüye sahip bir işlevi zamanlayın ve bu temel optimizasyonun Python'un performansı için önemini göreceksiniz.
Alex Martelli

3
@ msw, bence "pratiklik saflığı yener" ;-).
Alex Martelli

6

Modül kapsamındaki değişkenleri modül içinden ayarlamanız gerekiyorsa, sorun globalnedir?

# my_module.py

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

Böylece:

>>> 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
Evet, her zaman ("her zaman" "Python öğrendiğim son birkaç ay" olarak tanımlanır) bu global but not reallybildirimin şaşırtıcı olduğunu buldum . Modül ad alanlarından önce gelen tarihi bir kalıntı olabileceğini düşünüyorum.
msw

1
Orijinal soru, adı bir dize (şu anda aradığımla aynı şey) tarafından verilen bir özniteliğin nasıl ayarlanacağını sormaktır, bu yüzden bu yardımcı olmaz.
Curt

6

Python 3.7'de, __getattr__modül düzeyinde ( ilgili cevap ) kullanabileceksiniz.

Başına PEP 562 :

def __getattr__(name):
    if name == "SOME_CONSTANT":
        return 42
    raise AttributeError(f"module {__name__} has no attribute {name}")

-1
  1. Yapmazsın. Yapardınglobals()["SOME_CONSTANT"] = 42
  2. Yapmazsın. Dinamik olarak oluşturulan içeriği modül dışında bir yerde depolarsınız.

Evet, SOME_CONSTANTçalışma zamanında hesaplanan tam olarak sabit değildir. Ve globals()sizin için uygun değilse , özelliklerini değiştirmek için başka bir modüle ulaşmanız gerekir; bu insanları merak etmeye zorlar.
msw

3
Sabit ve değişken karşılıklı birbirini dışlar. Sabit ve dinamik olarak üretilmez. Oluşturduğum değerler her zaman aynıdır ve aritmetikten tasarruf etmek ve benim adımımda yazmak için daha fazla "sabit" e göre belirlenir.
Matt Joiner
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.