Rumah > Soal Jawab > teks badan
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
Mengikut peraturan, adakah inside
函数里,为什么x不指向原来的'outside'
string telah dimasukkan pada masa ini?
Bukankah pembolehubah yang tidak ditentukan seharusnya menghasilkan NameError
? Mengapa tidak di sini?
Saya pada asalnya menyangka bahawa rentetan dan senarai adalah serupa dengan penunjuk dalam C, tetapi nampaknya itu tidak berlaku sekarang Jika boleh, saya berharap untuk memberi sedikit pengenalan kepada perkara ini, terima kasih.
我想大声告诉你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 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: Ininside
中, 已经有了赋值语句, 所以对于x
,他已经不会从enclosing
或者global
甚至bulitin
里面去查找, 它已经被认定在local
域了, 只是这个值并没有和真正的对象'inside'
建立起绑定关系, 因为代码没有运行到真正的赋值语句, 所以, 会触发这个UnboundLocalError
. 而为什么那个列表会可以那样做, 因为他们两个是完全不同的操作, 同样都是print(id(x))list的操作字节码是LOAD_DEREF
, 而字符串的操作字节码是LOAD_FAST
, 而x[:]=[1,2,3]/x='inside'分别对应的字节码又是STORE_SLICE+3
和 STORE_FAST
, 前者是在原来的基础上修改, 而后者是重新指向新的对象, 而这两种方式的区别, 决定了,它们在构建函数时, 以怎样的形式存放x
, 这个就涉及到python函数
构建的原理了, 有兴趣可以看看源码中的object/ceval.c源码
, 这是虚拟机运行的原理, 关于这个问题可以简单看我另一篇文章, 比较简单将UnboundLocalError
: Mari kita bincangkan tentang UnboundLocalError ajaib: pembolehubah tempatan x dirujuk sebelum tugasan
某草草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...
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.