彻底搞懂python函数传值or引用问题

本文详细解析了Python函数参数传递方式,包括变量与对象的概念、可更改与不可更改对象的区别,以及如何通过实例理解Python中传值与传引用的区别。

作者: winterTTr (转载请注明)

转自: http://blog.youkuaiyun.com/winterttr/article/details/2590741

我想,这个标题或许是很多初学者的问题。尤其是像我这样的对C/C++比较熟悉,刚刚进入python殿堂的朋友们

。C/C++的函数参数的传递方式根深蒂固的影响这我们的思维--引用?传值?究竟是那种呢。

呵呵,语言的特性决定了是使用的方法,那么,现在我们来探究一下python的函数参数传递方式。

在开始之前,我们有必要分清一下python的一些基础概念。

首先要说的是:变量 与 对象

在python中,类型属于对象,变量是没有类型的,这正是python的语言特性,也是吸引着很多pythoner的一点。所有的变量都可以理解是内存中一个对象的“引用”,或者,也可以看似c中void*的感觉。所以,希望大家在看到一个python变量的时候,把变量和真正的内存对象分开。

类型是属于对象的,而不是变量。这样,很多问题就容易思考了。

例如: 

nfoo = 1   #一个指向int数据类型的nfoo(再次提醒,nfoo没有类型)

lstFoo = [1]   #一个指向list类型的lstFoo,这个list中包含一个整数1。

对应于上一个概念,就必须引出另了另一概念,这就是“可更改”(mutable)与“不可更改”(immutable)对象

对于python比较熟悉的人们都应该了解这个事实,在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象。那么,这些所谓的可改变和不可改变影响着什么呢?

还是上面的例子:

nfoo = 2        

这时,内存中原始的1对象因为不能改变,于是被“抛弃”,另nfoo指向一个新的int对象,其值为2

lstFoo[0] = 2  

更改list中第一个元素的值,因为list是可改变的,所以,第一个元素变更为2,其实应该说有一个新int对象被指定给lstFoo 所指向的对象的第一个值,但是对于lstFoo 来说,所指向的对象,并没有变化,就是这个看似void*的变量所指向的对象仍旧是刚刚的那个有一个int对象的list。(听着有点晕吧,仔细琢磨一下就明白了,嘿)

好了,被我这么填鸭似的复习了一下python的基础知识,改转回题目的问题了,Python的函数参数传递:传值?引用?

对于变量(与对象相对的概念),其实,python函数参数传递可以理解为就是变量传值操作(注意哦,我说的是变量,不是对象  =_= )

接着说例子好了:

def ChangeInt( a ):

      a = 10  # change the number

nfoo = 2 

ChangeInt(nfoo)

print nfoo #结果是2

这时发生了什么,有一个int对象2,和指向它的变量nfoo,当传递给ChangeInt的时候,按照传值的方式,复制了变量nfoo的值,这样,a就是nfoo指向同一个Int对象了,函数中a=10的时候,发生什么?

(还记得我上面讲到的那些概念么),int是不能更改的对象,于是,做了一个新的int对象,另a指向它(但是此时,被变量nfoo指向的对象,没有发生变化),于是在外面的感觉就是函数没有改变nfoo的值,看起来像C++中的传值方式。

def ChangeList( a ):

      a[0] = 10  # change the number

lstFoo = [2]

ChangeList(lstFoo )

print nfoo #结果是[10]

当传递给ChangeList的时候,变量仍旧按照“传值”的方式,复制了变量lstFoo 的值,于是a和lstFoo 指向同一个对象,但是,list是可以改变的对象,对a[0]的操作,就是对lstFoo指向的对象的内容的操作,于是,这时的a[0] = 10,就是更改了lstFoo 指向的对象的第一个元素,所以,再次输出lstFoo 时,显示[10],内容被改变了,看起来,像C++中的按引用传递。

恩,现在是不是对python中的变量和对象的概念有了更深入的理解了呢?

通过我上面的解释,我想大家也可以自己搞定其他类型对象的传递问题了吧。

在调用函数 `Get_NotNullColName` 时,参数的递方式直接影响函数的执行效果。根据函数设计的目的,它通常用于从指定表中获取非空列的名称,因此参数应包含表名或与表相关的查询条件。 函数调用时,参数递需遵循数据库函数定义中的参数顺序和类型。若函数定义如下: ```sql CREATE OR REPLACE FUNCTION Get_NotNullColName(p_table_name IN VARCHAR2) RETURN VARCHAR2 ``` 则调用语句应为: ```sql SELECT Get_NotNullColName('DCTESTBED_XMLDATA_1034178') FROM dual; ``` 此时,参数 `'DCTESTBED_XMLDATA_1034178'` 为表名,采用的是按递的方式,即函数接收的是该字符串的副本,不会影响原始变量[^1]。 若函数内部逻辑涉及动态 SQL 或依赖系统表(如 `ALL_CONSTRAINTS`、`ALL_CONS_COLUMNS` 等),则需确保入的表名有效,并且当前用户具有访问该表及其相关系统视图的权限。例如: ```sql SELECT Get_NotNullColName('EMPLOYEES') FROM dual; ``` 若函数支持多个参数,例如入列名或查询条件,则调用方式应与函数定义保持一致。例如,若函数定义为: ```sql CREATE OR REPLACE FUNCTION Get_NotNullColName(p_table_name IN VARCHAR2, p_condition IN VARCHAR2) RETURN VARCHAR2 ``` 则调用方式应为: ```sql SELECT Get_NotNullColName('DCTESTBED_XMLDATA_1034178', 'FILENAME = ''SFZ-2 性能1.docx''') FROM dual; ``` 此时,第二个参数为查询条件字符串,需注意 SQL 注入风险及字符串拼接格式的正确性[^3]。 此外,若函数被用作工具调用的一部分(如在 AI 驱动的应用中),则需将函数注册为可用工具,并通过解析响应中的 `tool_call` 来执行函数调用。例如: ```python available_functions = { 'Get_NotNullColName': Get_NotNullColName } for tool in response.message.tool_calls or []: function_to_call = available_functions.get(tool.function.name) if function_to_call: print('Function output:', function_to_call(**tool.function.arguments)) else: print('Function not found:', tool.function.name) ``` 该方式适用于将函数作为 API 接口调用的一部分,需确保参数以字典形式递,并与函数定义一致[^2]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值