针对如何在Python中从外部获取/设置函数的局部变量?和python函数调用局部变量这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展len()函数在python3中是如何实现的,以及如何在
针对如何在Python中从外部获取/设置函数的局部变量?和python函数调用局部变量这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展len() 函数在python 3 中是如何实现的,以及如何在python 中找到内置函数的源代码?、python – 如何从堆栈跟踪中提取局部变量?、python 入门基础教程 07 python 的局部变量和全局变量、Python 学习笔记——函数中的局部变量和全局变量等相关知识,希望可以帮助到你。
本文目录一览:- 如何在Python中从外部获取/设置函数的局部变量?(python函数调用局部变量)
- len() 函数在python 3 中是如何实现的,以及如何在python 中找到内置函数的源代码?
- python – 如何从堆栈跟踪中提取局部变量?
- python 入门基础教程 07 python 的局部变量和全局变量
- Python 学习笔记——函数中的局部变量和全局变量
如何在Python中从外部获取/设置函数的局部变量?(python函数调用局部变量)
如果我有一个函数(在Python 2.5.2中)像这样:
def sample_func(): a = 78 b = range(5) #c = a + b[2] - x
我的问题是:
- 如何在 不 使用函数内部的 locals()的 情况下 从外部 获取 函数的局部变量(a,b)?(反射的种类)
- 是否可以从外部设置局部变量(例如 x ),以便注释行起作用?(我知道这听起来很奇怪)。
提前致谢。
编辑 :
每个人都在寻找用例。但这是一个奇怪的情况。(不要怪我,我没有创造出来)。这是场景:
- 我有一个包含python函数的加密python源文件。
- AC扩展模块将其解密并在内存中构建该功能。
- 一个主要的python程序首先使用该加密文件位置调用C扩展名。
- 然后,主程序调用已在内存中构建的函数(通过C扩展)
- 但是主程序需要知道该函数的局部变量(不要问我为什么,不是我)
- 由于某些(该死的)原因,主程序也需要设置一个变量(最奇怪的)
答案1
小编典典否。未运行的函数没有本地语言;这只是一个功能。询问如何在不运行时修改函数的本地变量,就像询问如何在不运行时修改程序的堆一样。
但是,如果确实需要,可以修改常量。
def func(): a = 10 print aco = func.func_codemodified_consts = list(co.co_consts)for idx, val in enumerate(modified_consts): if modified_consts[idx] == 10: modified_consts[idx] = 15modified_consts = tuple(modified_consts)import typesmodified_code = types.CodeType(co.co_argcount, co.co_nlocals, co.co_stacksize, co.co_flags, co.co_code, modified_consts, co.co_names, co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno, co.co_lnotab)modified_func = types.FunctionType(modified_code, func.func_globals)# 15:modified_func()
这是骇客,因为无法知道co.co_consts中的哪个常量是哪个;这使用一个哨兵值来解决。根据您是否可以充分限制用例,就足够了。
len() 函数在python 3 中是如何实现的,以及如何在python 中找到内置函数的源代码?
如何解决len() 函数在python 3 中是如何实现的,以及如何在python 中找到内置函数的源代码??
任务从一个简单的 LeetCode 问题开始。我正在学习 python 并试图解决 leetcode 中的一个问题,其中我在 while 循环中检查条件时使用了 len()。我很好奇如果我写 len(nums) 而我的程序会做更多的计算。为了找到这个,我开始寻找源代码。
while i < len(nums):
#if both the numbers are same we can pop the ith number
#else just increase the index and return the length in the end.
if nums[i] == val:
nums.pop(i)
else:
i+=1
return len(nums)
现在,我有两个问题:
- 如何在不手动在 GitHub 上搜索源代码的情况下查找 内置 函数的源代码?
- len 函数在内部如何工作?
我有两个假设:
- Python 将所有事物都视为一个对象,并且它们有一个名为 length(或类似名称)的属性,并且每当我从列表中弹出一个元素时。此属性减 1。
- 另一个假设是 python 以某种方式迭代整个对象并返回长度。
我得到了源代码。然而,它再次使用另一个函数来计算长度。
static PyObject *
builtin_len(PyObject *module,PyObject *obj)
/*[clinic end generated code: output=fa7a270d314dfb6c input=bc55598da9e9c9b5]*/
{
Py_ssize_t res;
res = PyObject_Size(obj);
if (res < 0) {
assert(PyErr_Occurred());
return NULL;
}
return PyLong_FromSsize_t(res);
}
@Antti Haapala 在解释答案方面做得很好。但是,它没有回答我的问题。
这些是我在堆栈溢出中发现的一些相关问题:
How to view source code of function in python?
explanation of C implementation python''s len function
解决方法
问题 0
我很好奇如果我写了 len(nums) 而我的程序会做更多的计算。
Python wiki 的所有内置数据结构的 TimeComplexity 页面中记录了这方面的一个方面。列表的 len()
是 O(1)
。
如果你的意思是类似
如果我执行 n = len(nums)
,然后每次从列表中删除时手动从 n
中减去 1,我的程序会更快吗
那又是一个完全不同的问题了,答案很可能(测量它!)是(也许有点不直观)“否”,因为 len()
是用 C 实现的(快!)并解释 Python 代码( n -= 1
) 并且执行速度较慢。
问题 1
如何在不手动在GitHub上搜索源代码的情况下查找内置函数的源代码?
作为先决条件,您需要
- 知道如何阅读 C 并理解控制流程
- 能够跟踪调用图(在您的脑海中、在文本文件中、在记事本中)
- 对从哪里开始查看源代码有一个直觉
GitHub 的源代码搜索是可以通过的,但是您将有更好的时间下载源代码并使用更好的 IDE 在代码中跳转。
对于模块中的内置函数,我会开始搜索例如mathmodule.c
用于数学函数等。
对于对象的实现,例如listobject.c
。这是相当合乎逻辑的(大部分时间)。
问题 2
- 您已经找到
builtin_len
。 - 您可以看到它调用了
PyObject_Size
。这被定义为 here。 - 它执行
PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence;
,即获取指向对象类型头的指针,以及对象的序列相关方法的“槽”(不要与 Python 用户空间槽混淆)。 - 如果该方法集合包含有效的
sq_length()
函数,则调用它:Py_ssize_t len = m->sq_length(o);
如果该长度有效,则返回它,并且len()
包装裸size_t
转换为 Python 长对象并将其传递给您。 - 如果失败,则调用
PyMapping_Size
。 - 它的作用与
sq_length
类似,只是使用映射方法tp_as_mapping
和mp_length
。 - 如果所有这些都失败了,则会使用
type_error()
帮助程序引发 TypeError。
Here in listobject.c
,您可以看到 list_length()
是如何连接为列表对象的 sq_length
。
该函数仅调用 Py_SIZE()
[https://docs.python.org/3/c-api/structures.html#c.Py_SIZE],这是一个访问 ob_size
所有 PyVarObject 都有的字段。
有关查找 Python 的列表对象如何使用 ob_size
的文档是 here。
至于带有 __len__
的自定义类型如何与所有这些相关联,我记得带有 __len__
的对象将使其 sq_length()
调用 Python 可调用对象(如果存在),然后该值通过 C 代码“传送”回您的 Python 代码。
python – 如何从堆栈跟踪中提取局部变量?
假设我有一个引发意外异常的函数,所以我将它包装在ipdb中:
def boom(x,y):
try:
x / y
except Exception as e:
import ipdb; ipdb.set_trace()
def main():
x = 2
y = 0
boom(x,y)
if __name__ == '__main__':
main()
我可以向上移动堆栈以找出x和y具有的值:
$python crash.py
> /tmp/crash.py(6)boom()
5 except Exception as e:
----> 6 import ipdb; ipdb.set_trace()
7
ipdb> u
> /tmp/crash.py(11)main()
10 y = 0
---> 11 boom(x,y)
12
ipdb> p y
0
但是,在调试时,我想把调试器放在最顶层:
def boom(x,y):
x / y
def main():
x = 2
y = 0
boom(x,y)
if __name__ == '__main__':
try:
main()
except Exception as e:
import ipdb; ipdb.set_trace()
我可以显示回溯,但我无法查看函数内部的变量:
$python crash.py
> /tmp/crash.py(14)ipdb.set_trace()
ipdb> !import traceback; traceback.print_exc(e)
Traceback (most recent call last):
File "crash.py",line 12,in ipdb> d # I want to see what value x and y had!
*** Newest frame
异常发生时,异常对象显然仍然具有对堆栈的引用.我可以在这里访问x和y,即使堆栈已经解开了吗?
要手动提取值:
ipdb> !import sys
ipdb> !tb = sys.exc_info()[2]
ipdb> p tb.tb_next.tb_frame.f_locals
{'y': 0,'x': 2}
更好的是,您可以使用异常在该堆栈上显式执行事后调试:
import sys
def boom(x,y)
if __name__ == '__main__':
try:
main()
except Exception as e:
# Most debuggers allow you to just do .post_mortem()
# but see https://github.com/gotcha/ipdb/pull/94
tb = sys.exc_info()[2]
import ipdb; ipdb.post_mortem(tb)
这让我们直接看到了令人讨厌的代码:
> /tmp/crash.py(4)boom()
3 def boom(x,y):
----> 4 x / y
5
ipdb> p x
2
python 入门基础教程 07 python 的局部变量和全局变量
局部变量
要谈局部变量和全局变量的技术前提是对函数有一定的理解,我们先在这里简单说明一下 Python 的函数,Python 有自带的函数也可以使用第三方工具包了外部引用函数,有的时候用户自己可以自主开发一些特定功能的函数我们称之为自定义函数。用户怎么才能自己定义函数呢?Python 规定的自定义函数语法结构如下:
def function_name(parameters):
(TAB)statement1
(TAB)statement2
(TAB)statement3
(TAB)etc.
第 1 行是定义函数名及函数的参数,请注意函数右括号后有一个冒号!第 2-5 行是函数语句块。需要注意的是函数名下的每条语句前都要用 TAB 键缩进一下,否则会认为是非本函数的语句块里的语句,而是与函数同级的程序的某条语句。Python 函数体不用花括号将语句块括起来而是用 TAB 来区分语句是函数里的还是不是函数的。函数无返回值类型,行参也无数据类型说明。
自定义函数可以像 C 语言一样在其他地方被其他程序或语句调用,调用自定函数时不需要使用 def 这个关键字。我们举例说明一下。
#define function: add
def add(x, y):
z = x + y
return z
#define main function
def main():
a = 12
b = 13
#function ''add'' called
c = add(a, b)
print c
#programme entry
main()
print ''End!''
程序代码从第 13 行开始执行,从第 2 行到第 11 行分别定义了 add 和 main 两个函数。add 函数有两个形参 x 和 y,而 main 函数无形参也无返回值。程序从第 13 行开始执行然后跳转到自定义 main 函数的的第 7 行、8 行和第 10 行,当程序执行到第 10 行的时候又跳转到 add 函数的第 3 行、第 4 行将和返回给调用函数 main,当 add 执行完以后返回到调用函数 main 函数,同时会把返回值赋值给第 10 行的等号左边的 c 这个变量,接下来执行第 11 行,打印求和结果,执行完 11 行后 main 被全部执行完毕返回到第 13 行的下一行第 14 行打印出字符串’End!’, 至此整个程序结束。
有了函数的基本概念以后,我们再来聊聊 Python 变量的局部变量问题。顾名思义局部变量肯定生活在某个局部地方,那什么叫局部变量呢?定义在函数体内的变量叫局部变量,因此我们可以很快得到全局变量的定义,那就是定义在函数体外的变量时全局变量。局部变量只可被本函数使用,全局变量可以被所有语句访问使用。
def f1():
x = 12
print x
def f2():
y = 13
print y
def f3():
print x
print y
def main():
f1()
f2()
%f3()
main()print ''End!''
此时第 13 行代码是被注释掉的,如果打开第 13 行会报错如下:
>>>1213Traceback (most recent call last):
File "F:/Python27/t2.py", line 14, in <module>
main()
File "F:/Python27/t2.py", line 13, in main
f3()
File "F:/Python27/t2.py", line 8, in f3 print xNameError: global name ''x'' is not defined
>>>
错误是说 main 函数在调用函数 f3 时发现 f3 函数某一行有问题 (的第 8 行)“print x” 里的 x 没有定义。我猜设计者是想打印 f1 定义的 x 想打印出 12,对么?但 x 定义在自定义函数 f1 里,x 此时是局部变量不能被除 f1 函数之外的函数或者语句使用,故报错。由于局部变量定义在函数体里,故多个函数可以在各自函数体内使用相同的变量名作为自己的变量。
全局变量
全局变量没有定义在任何函数体内,或者可以这么说和 main 函数属于同一级,全局变量可以被自定义的函数访问使用,如果函数想读去某个全局变量没有特别的要求,直接使用即可。但是如果某函数想在函数里修改某个全局变量,Python 语言要求在修改前用 global 语句声明一下这个变量是全局的才能修改这个全局变量。
def printLocalx():
x = 12
print ''f1 local x = '',
print x
def printLocaly():
y = 13
print ''f2 local y = '',
print y
def readGlobal():
print ''f3 read global x = '',
print x
print ''f3 read global y = '',
print y
def modifyGlobal():
global x
print ''f4 write x = -1''
x = -1
def main():
printLocalx()
printLocaly()
readGlobal()
modifyGlobal()
x = 200
y = 100
main()
print ''after modified global x = '',
print x
print ''End!''
此时由于程序定义了全局变量 x 和 y,故 readGlobal 函数的两条打印语句是不会报语法错误的。全局变量可被任何子函数访问使用,在 readGlobal 函数里 (第 11 行和第 13 行) 读 x 和 y 变量的值,没有问题。而在 modifyGlobal 函数体里 (第 17 行) 将 x 赋值为 - 1,如果自定义函数体修改全局变量,首先要像第 15 行那样声明一下这个 x 是全局的变量,只有这样才能修改全局的 x 变量。如果去掉第 15 和 16 行,第 17 行的 x 将被看做 modifyGlobal 函数的局部变量。
程序执行结果如下所示:
f1 local x = 12f
2 local y = 13
f3 read global x = 200
f3 read global y = 200
f4 write x = -1after
f4 modified global x = -1
End!
Python 学习笔记——函数中的局部变量和全局变量
- 局部变量是函数内部的占位符,与全局变量可能重名但不同(当变量为基本数据类型时)。
- 函数定义或调用结束后,局部变量将被释放(不再存在),在函数外部调用局部变量将出错(变量未定义)。
- 在函数内使用global保留字可使用全局变量。
- 当局部变量为组合数据类型且未创建,等同于全局变量。
举例如下:
代码1:
def createList(a, b):
numbers = []
i = 0
while i < a:
print(f"At the top i is {i}")
numbers.append(i)
i = i + b
print("Numbers now: ", numbers)
print(f"At the bottom i is {i}")
createList(8, 2)
print("The numbers: ")
for num in numbers:
print(num)
运行结果:
At the bottom i is 4
At the top i is 4
Numbers now: [0, 2, 4]
At the bottom i is 6
At the top i is 6
Numbers now: [0, 2, 4, 6]
At the bottom i is 8
The numbers:
numbers未定义,因此for循环的输出为空 。
代码2:
numbers = []
def createList(a, b):
i = 0
while i < a:
print(f"At the top i is {i}")
numbers.append(i)
i = i + b
print("Numbers now: ", numbers)
print(f"At the bottom i is {i}")
createList(8, 2)
print("The numbers: ")
for num in numbers:
print(num)
运行结果:
At the top i is 0
Numbers now: [0]
At the bottom i is 2
At the top i is 2
Numbers now: [0, 2]
At the bottom i is 4
At the top i is 4
Numbers now: [0, 2, 4]
At the bottom i is 6
At the top i is 6
Numbers now: [0, 2, 4, 6]
At the bottom i is 8
The numbers:
0
2
4
6
可以看到,函数内部未定义numbers变量,numbers.append(i)直接调用了全局变量。
关于如何在Python中从外部获取/设置函数的局部变量?和python函数调用局部变量的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于len() 函数在python 3 中是如何实现的,以及如何在python 中找到内置函数的源代码?、python – 如何从堆栈跟踪中提取局部变量?、python 入门基础教程 07 python 的局部变量和全局变量、Python 学习笔记——函数中的局部变量和全局变量等相关知识的信息别忘了在本站进行查找喔。
本文标签: