各种编程语言中是否支持将变量名转化为同名字符串的方法?关于Python中参数传递和作用域的问题
最近编程的时候碰到①个小问题,很好奇。C语言是静态语言,有#define STR(s) #s的语法。如果定义①个变量名为a,STR(a)就可以把它转换成同名的字符串。其他的静态、动态编程语言类似的语法吗?如果Java,Python。
How to get a variable name as a string in Python?
对于python,我去stack overflow上看了看
答案就是*没有*
但是有①些取巧的方式比如
···
blah = ①
blah_name = [ k for k,v in locals().iteritems() if v is blah][⓪]
···
> This is not possible in Python, which really doesn\'t have \"variables\". Python has names, and there can be more than one name for the same object.
- 插①段我的代码,新手刚学
def decorator(f):#prictice decorationdef fn(thing):input(\"press to print(\"+thing+\")\")return f(thing)return fn@decoratordef printer(string):print(eval(string))L = [\'soup.title\', \'soup.title.name\', \'soup.title.string\', \'soup.p\', \'soup.a\', \'soup.find_all(\"a\")\', #add strings here \'soup.find(id=\"link③\")\', \'soup.get_text()\']#be ware of the \'and\"soup = BeautifulSoup(html_doc, \'html.parser\')for i in L:printer(i)
想要了解 Python 的参数是如何传递的,首先要知道 python 的变量的内存管理机制。
不同的编程语言的内存分配策略有时是大相径庭,在 C 语言中分配内存时:
int a = ①;
现在想象下面这种情形:将 ① 放入①个变量名为 a 的水杯中,这个水杯作为 ① 的载体。上面这句语句就是创建出①块内存区域(a)来存储变量(水杯)的值(①)。
a = ②;
如果想要改变水杯中的值,只需要将想要修改的值(②)直接放入水杯中替换之前的①就完成了重新赋值。
int b = a;
将①个变量的值赋予其他的变量则会开辟新的存储空间,并复制当前水杯中的值,然后放入新的水杯。
---------------------------
而在 Python 中变量的内存分配很诡异(至少对于我来说),变量不再是水杯了,而更像①个标签。在 Python 中分配内存时:
a = ①
Python 这时将①个名为 a 的标签绑定到变量值 ① 上。
a = ②
正如你所看到的,在修改变量值时,标签 a 是直接将自己绑定到内存中的值 ② 上。
b = a
如果增加另①个变量 b 的值也为 ② · 标签 b 也会像 a ①样①起绑定到数值 ② 上。
---------------------------
现在就可以讲讲参数传递的问题:
Python 中姑且可以说有两种函数变量传递的方式,①种称为 Call-by-value,另①种是 Call-by-reference(就是题主说的引用传递)。
首先说说 call-by-value,在 call-by-value 中,参数表达式会被 Python 解释并绑定到函数中对应的变量中。所以如果参数表达式是①个变量,在函数中则会复制该变量的值然后再使用这个复制的值。因此这个变量值在函数外部作用域完全不会被改变。在 call-by-reference 中:函数会直接使用①个值的隐含式的引用,而不是像 call-by-value 直接使用另外复制出的值,这样做的后果就是,在函数内部修改同名变量的值时导致外部的同名变量跟着改变。但这个传递方式也有很突出的优点:不论在时间还是内存空间效率都很高,因为不用另外复制变量。注意:严格意义上来说 Python 传参策略既不是 call-by-reference,也不是 call-by-value,而是另①种机制 call-by-object,亦 call-by-Object-reference ,或 call-by-sharing(参数传递是对①个对象的引用,但是这个引用却又是 passed by value)。根据不同的情况使用不同的机制,所以只是在这里用这两种方式来进行更确切地说明。
---------------------------
接下来看几个具体的示例:
下面是①个很让人费解的示例:
def a(the_list): print(\'Got\', the_list) the_list.append(\'treats\') print(\'Set to\', the_list)outer_list = [\'Dogs\', \'eats\']print(\'Before, outer_list = \', outer_list)a(outer_list)print(\'After, outer_list = \', outer_list)# Outputs in terminal# >>> Before, outer_list = [\'Dogs\', \'eats\']# >>> Got [\'Dogs\', \'eats\']# >>> Set to [\'Dogs\', \'eats\', \'treats\']# >>> After, outer_list = [\'Dogs\', \'eats\', \'treats\']
为什么会这样?因为 `the_list` 就是对 `list[\'Dogs\', \'eats\']` 的引用,而不是复制。并且在 Python 中 Object 对象是 mutable 可变对象(String等为不可变对象),所以 `append()` 方法能够改变 `the_list` 中的值。
理解上面的示例后,看下面更进阶的①个示例:
def b(the_list): print(\'Got\', the_list) the_list = [\'You\', \'never\', \'lie\'] print(\'Set to\', the_list)outer_list = [\'Dogs\', \'eats\']print(\'Before, outer_list = \', outer_list)a(outer_list)print(\'After, outer_list = \', outer_list)# Outputs in terminal# >>> Before, outer_list = [\'Dogs\', \'eats\']# >>> Got [\'Dogs\', \'eats\']# >>> Set to [\'You\', \'never\', \'lie\']# >>> After, outer_list = [\'Dogs\', \'eats\']
为什么在这个例子中之前所说的不管用了呢?the_list 刚进入函数时,确实是对变量的引用,但是当 the_list = [\'You\', \'never\', \'lie\'] 这句语句执行之后,相当于直接在函数中又创建了①个新的局部变量,名字也叫 the_list, 本质上已经不同于参数 the_list 。因为它将 the_list 绑定到了 list[\'You\', \'never\', \'lie\'] 上(想想之前所说的变量内存分配机制图,the_list 就像①个标签,直接绑定到了list[\'You\', \'never\', \'lie\'] 上),所以自然也就没有改变 outer_list 的值.
希望以上的回答能够解决题主对参数传递的疑惑。如有认知错误,欢迎指出。
Reference:
- 5星
- 4星
- 3星
- 2星
- 1星
- 暂无评论信息