函数中的声明和变量的定义

  • 声明与定义比较
  • 前向引用
  • 函数属性
  • 内部/内嵌函数
    • 函数应用:打印图形和数学计算
  • 变量作用域
  • 全局变量与局部变量
  • 局部变量
  • 全局变量
  • globa语句
  • 可变类型的全局变量

声明与定义比较

​ 在某些编程语言里,函数声明和函数定义区分开的,一个函数声明包括提供对函数名,参数的名字(传统上还有参数的类型),但不必给出函数的任何代码,具体的代码通常属于函数定义的范畴。
​ 在声明和定义有区别的语言中,往往是因为函数的定义可能和其声明放在不同的文件中。python将这两者视为一体,函数的子句由声明的标题行以及随后的定义体组成的。

前向引用

和其他高级语言类似python也不允许在函数未声明之前,对其进行引用或者调用。
我们下面给出几个例子来看一下:

def func():print("in func()")bar()
print(func())
#会报错

修改:现在定义函数bar()在函数func()前给出bar()声明:

#定义函数的前后顺序都可以!
def func():print("in func()")bar()
def bar():print("in bar()")
func()

现在我们可以安全的调用func(),而不会出现任何问题:

func()
in func()
in bar

事实上,我们甚至可以在函数bar()前定义函数func():

def func():print("in func()")bar()
def bar():print("in bar()")

Amazing依然可以很好的运行,不会有前向引用的问题:

func()
in func()
in bar
这段代码是正确的因为即使(在 foo()中)对 bar()进行的调用出现在 bar()的定义之前,但 foo()本身不是在 bar()声明之前被调用的。换句话说,我们声明 foo(),然后再声明bar(),接着调用 foo(),但是到那时,bar()已经存在了,所以调用成功。

注意 ,foo()在没有错误的情况下成功输出了’in foo()’。名字错误是当访问没有初始化的标识符时才产生的异常 。

函数属性

你可以获得每个 pyhon 模块,类,和函数中任意的名字空间。你可以在模块 foo 和 bar 里都有名为 x 的一个变量,,但是在将这两个模块导入你的程序后,仍然可以使用这两个变量。所以,即使在两个模块中使用了相同的变量名字,这也是安全的,因为句点属性标识对于两个模块意味了不同的命名空间,比如说,在这段代码中没有名字冲突:

import foo, bar
print(foo.x + bar.x)

函数属性是 python 另外一个使用了句点属性标识并拥有名字空间的领域。

def foo():'foo()-- properly created doc string'def bar():passbar.__doc__='Oops,forgot the doc str above'
bar.version =0.1

#按住shift在空白处打开 执行时在中间加-i
PS C:\Users\asus\Desktop\pythondemo测试\小巷> python -i band.py
>>> foo.__doc__
'foo()-- properly created doc string'
>>>

​ 上面的 foo()中,我们以常规地方式创建了我们的文档字串,比如, 在函数声明后第一个没有赋值的字串。当声明
bar()时, 我们什么都没做, 仅用了句点属性标识来增加文档字串以及其他属性。我们可以接着任意地访问属性。下面是一个使用了交互解释器的例子。(你可能已经发现,用内建函
数 help()显示会比用__doc__属性更漂亮,但是你可以选择你喜欢的方式)

>>> help(foo)
Help on function foo in module __main__:foo()foo() -- properly created doc string>>> bar.version
0.1
>>> foo.__doc__
'foo() -- properly created doc string'
>>> bar.__doc__
'Oops, forgot the doc str above'
>>>

注意我们是如何在函数声明外定义一个文档字串。然而我们仍然可以就像平常一样,在运行时刻访问它。然而你不能在函数的声明中访问属性。换句话说,在函数声明中没有’self‘这样的东西让你可以进行诸如_dict_[‘version’] = 0.1 的赋值。这是因为函数体还没有被创建,但之后你有了函数对象,就可以按我们在上面描述的那样方法来访问它的字典。另外一个自由的名字空间!

内部/内嵌函数

在函数体内创建另外一个函数(对象)是完全合法的,这种函数叫做内部/内嵌函数。
最明显的创造内部函数的方法是在外部函数的定义体内定义函数(用def关键字),如在:

def foo():def bar():print("bar() called.")print("foo() called")bar()
foo()
bar()

我们将以上代码置入一个模块中,如inner.py,然后运行,我们会得到如下输出:

bar() called.
foo() called
Traceback (most recent call last):File "<stdin>", line 1, in <module>
NameError: name 'bar' is not defined
>>>
http://www.pythontutor.com/visualize.html#mode=edit
将简单的代码拷贝进去,可以查看执行的步骤过程
内部函数一个有趣的方面在于整个函数体都在外部函数的作用域(即是你可以访问一个对象的区域;稍后会有更多关于作用域的介绍)之内。如果没有任何对 bar()的外部引用,那么除了在函数体内,任何地方都不能对其进行调用,这就是在上述代码执行到最后你看到异常的原因

另外一个函数体内创建函数对象的方式是使用lambda 语句。 稍后讲述。如果内部函数的定义包含了在外部函数里定义的对象的引用(这个对象甚至可以是在外部函数之外),内部函数会变成被称为闭包(closure)的特别之物。

函数应用:打印图形和数学计算

函数的嵌套调用;

程序设计的思路,复杂问题分解为简单问题。

  • 思考1:编程实现:

    • 写一个函数打印一条横线

    • 打印自定义行数的横线

      举例子说明:

#打印一行方法一
# def foo():
#   for i in range(5):
#       dar()
# def dar():
#   print("-",end=" ")
# foo()#打印一行方法二:
# def line():
#   print("-"*15)
# line()#打印多条横线的方法一:
# def line():
#   print("-"*15)
# line()
# def lines(n):
#   for i in range(n):
#       line()
# lines(5)#打印多条横线方法二:
def printOneline():print("-"*30)def printNumline(num):a=0
#因为prinOneline函数已经完成了打印横线的功能
#只需要多次调用此函数即可while a<num:printOneline()a+=1
printNumline(3)
  • 思考2:编程实现

    • 写一个函数求三个数的和
    • 写一个函数求三个数的平均值

参考代码

# 求3个数的和
def sum3Number(a,b,c):return a+b+c # return 的后面可以是数值,也可是一个表达式# 完成对3个数求平均值
def average3Number(a,b,c):# 因为sum3Number函数已经完成了3个数的就和,所以只需调用即可# 即把接收到的3个数,当做实参传递即可sumResult = sum3Number(a,b,c)aveResult = sumResult/3.0return aveResult# 调用函数,完成对3个数求平均值result = average3Number(11,2,55)print("average is %d"%result)

变量作用域

标识符的作用域是定义为其声明在程序的可应用范围,或者即是我们所说的变量可见性,换句话说,就好像在问你自己,你可以在程序里的哪些部分去访问一个制定的标识符,变量可以是局部域或者是全局域。

全局变量与局部变量

定义在函数内的变量有局部作用域,在一个模块中最高级别的变量有全局作用域。
“声明适用的程序的范围被称为了声明的作用域,在一个过程中,如果名字在过程的声明之内,它的出现即为过程的局部变量,否则的话,出现即为非局部的”.
全局变量的一个特征是除非被删除掉,否则它们的存活到脚本运行结束,且对于所有的函数,他们的值都是可以被访问的,然而局部变量,就像它们存放的栈,暂时的存在,仅仅只依赖于定义它们的函数现阶段是否处于活动,当一个函数调用出现时,其局部变量就进入声明它们的作用域,在那一刻,一个新的局部变量名为那个对象创建了,一旦函数完成,框架被释放,变量将会离开作用域。

举例子说明:

global_str='foo'
def foo():local_str='bar'return global_str+local_str
print(foo())#结果为:foobar
print(global_str)#结果为:foo
print(local_str)#会报错,因为局部变量只能在函数方法内部使用才有用
题目:
编写函数,实现求两个序列的交集。(为方便,序列类型可以直接统一采用列表)
方法一:
def foo():a=[1,2,3,4,5]b=[2,3,4]list1=list((set(a)&set(b)))print(list1)
foo()
结果:[2, 3, 4]
方法二:
def foo():a=[1,2,3,4,5]b=[2,3,4]list1=[val for val in a if val in b]print(list1)
foo()
结果:[2, 3, 4]

局部变量

例子:

def foo():a=666print('foo(),修改前a:\t',a)a=999print('foo(),修改后a:\t',a)def bar():a=8899print('bar(),a\t',a)

运行结果:

>>> foo()
foo(),修改前a:   666
foo(),修改后a:   999
>>> bar()
bar(),a  8899
>>>

可以看出:

  • 局部变量,就是在函数内部定义的变量
  • 不同的函数,可以定义相同的名字的局部变量,但是各用个的不会产生影响
  • 局部变量的作用,为了临时保存数据需要在函数中定义变量来进行存储,这就是它的作用

全局变量

同样,先看一下例子:

a=6699
def foo():print('foo(),a:\t',a)def bar():print('bar(),a:\t',a)print(foo())
print(bar())

运行结果:

foo(),a:  6699
None
bar(),a:     6699
None

讨论1:如果全局变量和局部变量名字相同?

a=8899
def foo():a=666print('foo(),修改前a:\t',a)a=888print('foo(),修改后a:\t',a)def bar():print('bar(),a:\t',a)foo()
bar()

运行结果为:

foo(),修改前a:   666
foo(),修改后a:  888
bar(),a:     8899

讨论2:全局变量,是能够在所有的函数中进行使用的变量,那么局部变量可否进行修改编程全局变量?

globa语句

如果将全局变量的名字声明在一个函数体内的时候,全局变量的名字能被局部变量给覆盖掉。

a=6699
def foo():global a print('foo(),修改前,a:\t',a)a=666print('foo(),修改后,a:\t',a)def bar():print('bar(),a:\t',a)
foo()
bar()

运行结果:

foo(),修改前,a:  6699
foo(),修改后,a:     666
bar(),a:     666

通过以上例子,我们可以观察出:

  • 在函数外边定义的变量叫做全局变量
  • 全局变量能够在所有的函数中进行访问
  • 如果在函数中修改全局变量,那么就需要使用global进行声明,否则出错
  • 如果全局变量的名字和局部变量的名字相同,那么使用的是局部变量的

可变类型的全局变量

先举2个例子:

例子1:

a=1
def foo():a+=1print(a)
foo()#内存地址改变了

运行后:

Traceback (most recent call last):File "C:\Users\asus\Desktop\pythondemo测试\小巷\band.py", line 108, in <module>foo()File "C:\Users\asus\Desktop\pythondemo测试\小巷\band.py", line 106, in fooa+=1
UnboundLocalError: local variable 'a' referenced before assignment

例子2:

li=['a','b']
def foo():li.append('c')print(li)
print(foo())
print(li)

运行结果:

['a', 'b', 'c']
None
['a', 'b', 'c']

函数中的声明和变量的定义相关推荐

  1. 【C 语言】指针间接赋值 ( 直接修改 和 间接修改 指针变量 的值 | 在函数中 间接修改 指针变量 的值 | 在函数中 间接修改 外部变量 的原理 )

    文章目录 一.直接修改 和 间接修改 指针变量 的值 二.在函数中 间接修改 指针变量 的值 三.在函数中 间接修改 外部变量 的原理 一.直接修改 和 间接修改 指针变量 的值 直接修改 指针变量 ...

  2. 变量的声明、变量的定义、变量的初始化

    变量的声明:用于向程序表明变量的类型和名字. 变量的定义:用于为变量分配存储空间,还可以为变量指定初始值. 变量的初始化:为变量指定初始值. 广义上来说,变量的声明有两种情况: 1.需要建立存储空间的 ...

  3. C语言中的关键字,变量的定义,变量的命名规则,交换两个变量的值,驼峰命名法【 C语言变量名命名法则】

    C语言结构 C语言中的关键字 变量 变量的定义 变量的命名规则 交换两个变量的值 驼峰命名法 C语言结构 上图中我们可以看到最外层是程序,内部是所有的构成,我们从最里面开始说明. 当我们用计算机语言来 ...

  4. lambda表达式或者匿名函数中为什么要求外部变量为final

    1.参考博客 关于Lambda表达式里面修改外部变量问题 JDK8之前,匿名内部类访问的局部变量为什么必须要用final修饰 2.匿名内部类 在jdk7之前,匿名内部类访问外部类的局部变量时,那么这个 ...

  5. C++ main函数中参数argc和argv相关定义与研究

    最近在研究opencv代码,在读取图上时遇到了一些问题.因此把它总结一下,方便学习. argc 则是 argument count的缩写,表示传入main函数的参数个数: argv 则是 argume ...

  6. c语言中被调用函数只需在主调函数中声明,其他函数中不用声明,求助,函数在其他函数中使用时要先声明后调用,这个没声明就用了...

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 如题,程序如下: #include #include //malloc,calloc,free,realloc头文件 #define LEN sizeof ...

  7. php 变量传给另外一个函数,将在一个函数中创建的PHP变量传递给另一个

    您可以将变量设为全局变量: function add_custom_price( $cart_object ) { global $newVar; foreach ( $cart_object-> ...

  8. JS函数简单的底层原理 -变量重复声明无效,隐式申明,变量提升,函数提升,以及堆栈内存的变化

    JS函数简单的底层原理 (个人理解): 1. 已经使用var申明且赋值,若再次申明,则第二次申明(不赋值)无效. 2.在同一个作用域下,只要是发生了同名,且变量完成赋值,后者会覆盖前者.存在两个相同的 ...

  9. 函数和变量的定义和声明

    函数和变量的定义和声明 一.函数的定义和声明 二.变量的定义和声明 一.函数的定义和声明 1.函数声明,无需实现该函数的功能.函数声明只是一个空壳,不会有特定的函数实现. 2.函数定义,必须实现该函数 ...

最新文章

  1. 前百度主任架构师创业,两年融资千万美元,他说AI新药研发将迎来黄金十年...
  2. java phantomjd linux_linux安装phantomjs
  3. 【BZOJ 2460 元素】
  4. linux下安装 ping 命令
  5. Android Fragment(二)
  6. Javascript中递归造成的堆栈溢出及解决方案
  7. atiken插值c++_c++插值代码
  8. Android小说阅读器案例
  9. 目前流行的数据分析软件有哪些?
  10. 编译安装nginx并实现反向代理负载均衡和缓存功能
  11. 事务机制:Redis能实现ACID属性吗?
  12. 在阿里(05)2022.04.19 周年啦
  13. 华为mt2l01 android5.1,华为MT2-L02/MT2-L01是什么型号手机?
  14. 【C/C++】程序环境,探索程序的执行过程(习得无上内功《易筋经》的第一步)
  15. 运筹说 第28期|论文速读之环境经济学中的影子价格
  16. 2.说明计算机环境下会计循环的八个流程,2020年云南自考《会计信息系统》要点复习(二)...
  17. 什么是sys文件系统
  18. 计算机文化基础实训小报制作,职业学院计算机文化基础课程实训指导书.doc
  19. c# 开源持久层 oracle,rexdb: 高性能的数据持久层(ORM)框架,查询性能是Hibernate的2.3倍,Mybatis的1.7倍。...
  20. ADP124ARHZ-1.8-R7 5.5 V输入、500 mA、低静态电流、CMOS线性调节器,31种固定输出电压选项

热门文章

  1. eclipse中各图标含义
  2. 【《自动控制原理(田玉平)》|课本知识点整理(一)】第 2 章 控制系统的输入 - 输出模型
  3. FreeCAD-0.19源码的编译配置(保姆级教程)
  4. [转]人不成熟的六大特征
  5. 豪斯曼检验matlab,面板工具变量与内生性操作及应用(固定随机、豪斯曼检验、过度识别检验、预测等)...
  6. android+sony+动态背景音乐,音乐流媒体时代,索尼ZX505给你不一样的感动
  7. 集美大学计算机专业属a类吗,集美大学是不是双一流大学,2020那些是一流大学和一流学科?...
  8. 硅谷钢铁侠-读书笔记
  9. 【调剂】其它计算机/软件调剂信息 21.3.16
  10. JAVA中常用容器的扩容