Rumah  >  Soal Jawab  >  teks badan

Mengenai skop pembolehubah python

Ada fungsi sebegini:

def outside():
    x=[]
    print(id(x))
    def inside():
        print(id(x))
        x[:]=[1,2,3]
        print(id(x))
    inside()
    print(id(x))
    print(x)

Tiada masalah berlaku selepas membuat panggilan, output:
140560473157960
140560473157960
140560473157960
140560473157960,

Tetapi gantikan x di dalam dengan rentetan, seperti berikut:

def outside():
    x='outside'
    print(id(x))
    def inside():
        print(id(x))
        x='inside'
        print(id(x))
    inside()
    print(id(x))
    print(x)

Apabila panggilan dibuat semula, ia menjadi:

140560473762872
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 8, in outside
  File "<stdin>", line 5, in inside
UnboundLocalError: local variable 'x' referenced before assignment
给我你的怀抱给我你的怀抱2712 hari yang lalu699

membalas semua(3)saya akan balas

  • 我想大声告诉你

    我想大声告诉你2017-05-18 10:55:10

    Jawab satu persatu dari senang ke susah, sebab itu pendapat saya yang rendah hati, jadi kalau ada yang nampak apa yang saya cakap tu tak betul, saya harap dia boleh tunjuk
    Sama dengan pointer dalam C: Ini betul, sebab dalam py< Dalam /code>, hampir semuanya adalah objek Malah penugasan pembolehubah memerlukan dahulu menjana objek dan kemudian membiarkan pembolehubah menghala ke ini. objek , dan objek juga dibahagikan kepada objek boleh ubah dan objek tidak boleh ubah Apabila beroperasi pada objek boleh ubah, ia akan menjejaskan objek lain menunjuk ke objek ini, contohnya: py里面, 几乎所有的事物都是对象, 就连变量赋值, 也是先生成对象, 再让变量指向这个对象,而对象还分可变对象不可变对象, 在对可变对象操作时, 是会影响到其他指向这个对象的变量, 例如:

    o = [1, 2, 3, 4]
    b = o
    print id(o)
    print id(b)
    b[1] = 123123
    print b
    print o
    输出:
    39946376
    39946376
    [1, 123123, 3, 4]
    [1, 123123, 3, 4]  # o指向的列表也被改变

    而对于不可变对象, 是直接就放弃旧的对象, 而指向新的对象, 例如:

    s = '123123'
    print id(s)
    s = '32131'
    print id(s)
    
    
    # 输出:
    41392768
    41392808
    

    所以你在操作python对象时, 需要谨记该对象是属于哪种类型, 你的操作又会不会因为这些特性而失败或者没达到自己想要的效果.

    未定义的变量: python在查找变量时, 将遵循LEGB的顺序, 只有都查找完毕还是没找到的情况下, 才会触发NameError异常, 这个可以参考我的一篇博文: Python: 作用域(scope) 和 LEGB

    UnboundLocalError: 这个问题是最常见, 也是最难解释的, 因为我们总是相当然地觉得, 它必定就会根据ELGB的顺序去查到变量;其实我们的理解并没错误, 只是我们忽略了一点:赋值语句

     x='outside'
        print(id(x))
        def inside():
            print(id(x))
            x='inside'
            print(id(x))

    Untuk objek tidak boleh ubah
    , objek lama terus ditinggalkan dan menunjuk ke objek baharu, contohnya: 🎜 rrreee 🎜Jadi apabila anda mengendalikan objek ular sawa, anda perlu mengingati jenis objek tersebut, dan sama ada operasi anda akan gagal atau tidak mencapai kesan yang diingini disebabkan oleh ciri-ciri ini.🎜 🎜🎜Pembolehubah tidak ditentukan🎜: Apabila python mencari pembolehubah, ia akan mengikut susunan LEGB Hanya apabila carian selesai atau tidak dijumpai, pengecualian NameError akan dicetuskan catatan Blog saya: Python: Skop dan LEGB🎜 🎜🎜UnboundLocalError🎜: Masalah ini adalah yang paling biasa dan paling sukar untuk dijelaskan, kerana kami sentiasa mengambil mudah bahawa ia akan mencari pembolehubah mengikut susunan ELGB sebenarnya, pemahaman kami tidak salah, ia adalah adil bahawa kita mengabaikannya Satu perkara: Pernyataan tugasan, jika tiada pernyataan tugasan dalam segmen kod fungsi, maka masalah ini tidak akan berlaku, tetapi mengapa ralat berlaku apabila pernyataan tugasan muncul berkaitan dengan skop Python, seperti yang dinyatakan di atas Satu artikel menyebut bahawa skop python tidak dinamik, tetapi statik, yang boleh dilihat dari lekukan fail skrip, jadi dalam kod: 🎜rrreee

    Ininside中, 已经有了赋值语句, 所以对于x,他已经不会从enclosing 或者global甚至bulitin里面去查找, 它已经被认定在local域了, 只是这个值并没有和真正的对象'inside'建立起绑定关系, 因为代码没有运行到真正的赋值语句, 所以, 会触发这个UnboundLocalError. 而为什么那个列表会可以那样做, 因为他们两个是完全不同的操作, 同样都是print(id(x))list的操作字节码是LOAD_DEREF, 而字符串的操作字节码是LOAD_FAST, 而x[:]=[1,2,3]/x='inside'分别对应的字节码又是STORE_SLICE+3STORE_FAST, 前者是在原来的基础上修改, 而后者是重新指向新的对象, 而这两种方式的区别, 决定了,它们在构建函数时, 以怎样的形式存放x, 这个就涉及到python函数构建的原理了, 有兴趣可以看看源码中的object/ceval.c源码, 这是虚拟机运行的原理, 关于这个问题可以简单看我另一篇文章, 比较简单将UnboundLocalError: Mari kita bincangkan tentang UnboundLocalError ajaib: pembolehubah tempatan x dirujuk sebelum tugasan

    balas
    0
  • 某草草

    某草草2017-05-18 10:55:10

    Anda menetapkan semula pembolehubah x baharu dalam fungsi dalam dan skop kedua-dua x adalah berbeza.
    UnboundLocalError disebabkan kerana anda mencetak pembolehubah yang tidak dimulakan dalam skop dalam.
    Lihat penjelasan ini untuk butiran:
    https://docs.python.org/2/faq...

    balas
    0
  • PHP中文网

    PHP中文网2017-05-18 10:55:10

    Pada asasnya Lin_R telah menjelaskannya dengan sangat jelas.
    Domain fungsi luar dan dalam adalah berbeza. Memandangkan anda memberikan nilai kepada x dalam fungsi dalam, apabila pembolehubah x digunakan dalam fungsi dalam, x dianggap berada dalam domain tempatan dalam. Pada masa ini, x tidak akan menggunakan nilai dalam medan lain. Jadi apabila mencetak(x), kerana x tidak mempunyai nilai permulaan, ralat berlaku. Walaupun adalah mungkin untuk menggunakan pembolehubah yang ditakrifkan tetapi tidak ditetapkan dalam C, Python tidak membenarkan ini.

    Dalam python3, terdapat pernyataan bukan tempatan yang boleh menyelesaikan masalah ini.

    def outside():
        x='outside'
        print(id(x))
        def inside():
            nonlocal x
            print(id(x))
            x='inside'
            print(id(x))
        inside()
        print(id(x))
        print(x)

    Perhatikan bahawa tidak mungkin menggunakan pernyataan global pada masa ini kerana tiada pembolehubah x dalam domain global.

    balas
    0
  • Batalbalas