python 基础5 初级函数

函数最重要的目的是方便我们重复使用相同的一段程序。将一些操作隶属于一个函数,以后你想实现相同的操作的时候,只用调用函数名就可以,而不需要重复敲所有的语句。

def my_len():           def   关键字
    li=[1,2,3,4,5,6]
    count = 0
    for i in li:
        count+=1
    return count      return 关键字
set=my_len()        函数的调用以及返回值的接收
print(set)

写函数时最好不要在函数中打印,要尽量以功能为导向。

返回值:

一 没有返回值的情况:

1.不写return

二 有返回值的情况:

return 的作用:1。返回一个或多个值

       2. 终止一个函数的继续。 这点很重要好多人都没有注意到这一点,有必要举个例子

举个例子:

def my_len():
    print(1)
    print(2)
    return None    #函数运行到return这里会直接跳出函数
    print(33)
print(44)
print(my_len())

结果:

44               ###为什么会先打印出44,因为程序第一步先运行到def这行,接着运行print(44)这行,而不是运行print(1),因为函数还没有调用。
1
2
None

 

1.返回一个值:什么数据类型都可以返回,返回什么就接收什么。

2.返回多个值:

如果用一个变量接收返回值,它会返回一个元祖,为什么会返回 一个元组,这里用到了python解析包的概念。python有一种一次给多个变量赋值的方法称为序列解包。

范例1

>>> 1,3           输入
(1, 3)               结果
>>> 2,3,6        输入
(2, 3, 6)            结果
x,y,z=1,2,3
print(x,y,z)           两个变量之间调换
x,y=y,x
print(x,y,z)

它允许函数返回一个以上的值并且打包成元组,然后通过一个赋值语句很容易进行访问。所解包的序列中的元素数量必须和放置在赋值符号(=)左边的变量数量完全一致,否则Python会在赋值时引发异常,

范例2:

def my_len():
    return 2, 3,4
set1,set2,set3=my_len()
print(set1,set2 ,set3)

结果:

(2, 3,4)

返回值用多个变量接收,那么返回值的个数应该和接收值的个数一样,否则会报错。

范例一:

def my_len():
    return 2, 3,4
set1,set2,set3=my_len()
print(set1,set2 ,set3)

结果:

2 3 4

参数

def func(lst):             接收参数叫形参
    count=0
    for i in lst:
        count+=1
    return count
l=[1,2,3,4,5] 
print(func(l))           传入参数叫实参

 

传函数可以传任意数据类型,并且传什么接收什么。

传参方式

站在传参数的角度上,一共有两种传参数的方式。

第一种:按照位置传参数。

第二种:按照关键字传参数。

传参顺序,这两种方式可以混用,但是注意位置传参不可以放在关键字传参之后。。一个位置只能接受一个参数,不允许接收多个参数。

接收参数方式

站在接收参数的角度上形参有4中参数

方式一:位置参数 。这是必传的

方式二:默认参数。可以传可以不传,不传就用自己的。

方式三:*args. 可以接收多个按位置传参

方式四:**kwargs可以接收多个按关键字传参

同时*args和**kwargs,又叫做动态参数

接收参数顺序:位置参数 ,*args,默认参数,**kwargs 

参数的接收和传入的顺序:位置参数,*args,  默认参数,**kwargs    注意不要把默认参数想象成关键字参数了。

def f(a,*args,b=8,**kwargs):
    print(a)
    print('*args',args)
    print('b',b)
    print('**kwargs',kwargs)

f(5,6,7,b=8,c=9,d=10)

结果:

5
*args (6, 7)
b 8
**kwargs {'c': 9, 'd': 10}

 

默认参数

默认参数:python为了简化函数的调用,提供了默认参数机制。

注意:1.默认参数必须放在必选参数之后,否则python会报错。

   2.默认参数必须指向的是不变的对象。看下边的默认参数的坑

范例

def classmate(name,sex=""):
    print("姓名:%s,性别:%s"%(name,sex))
    return
classmate("小红")
classmate("小花")
classmate("小蓝","")

结果:

姓名:小红,性别:男
姓名:小花,性别:男
姓名:小蓝,性别:女

默认参数的坑:(默认参数尽量不要用可变参数)

如果默认参数是可变对象时,每次调用函数,都是用的一个参数也就是一个id,所以只要你修改了默认参数的值,就相当于全部修改了,解决方法:把L射程[ ]

 范例:

def add_end(L=[]):
    L.append('we')
    return L
print(add_end())
print(add_end())
print(add_end([1]))#重新给L赋值了,相当于又另外开辟了一块内存空间.
print(add_end())#还是原来的L的内存空间

结果
['we'] ['we', 'we'] [1, 'we'] ['we', 'we', 'we']

纳尼,为什么不一直是['we'].

解答这个问题的方法:;

其实上面这个式子就等同于下面这个式子

li=[]
def add_end(L=li):
    L.append('we')
    return L
print(id(add_end()),add_end())
print(id(add_end()),add_end())
print(id(add_end([1])),add_end([1])) #重新给L赋值了,相当于又另外开辟了一块内存空间.
print(id(add_end()),add_end())#还是原来的L的内存空间

 

结果:

2142204139528 ['we', 'we']
2142204139528 ['we', 'we', 'we', 'we']
2142204163016 [1, 'we']
2142204139528 ['we', 'we', 'we', 'we', 'we', 'we']

动态参数

python中*和**的作用:

 *args: 接收所有按位置传的参数。中的*要求python创建一个名为args的空元祖,然后将接受到的值封装到这个元组中.   

def f(*w):
    print(w)
f(1,3,4,5)

结果:

(1, 3, 4, 5)

 

**kwargs 接受所有按关键字传的参数,它中的**要求python创建一个名为kwargs的空字典,然后将所有的值都封装到这个字典中.

def f(**w):
    print(w)
f(a=1,b=2,c=3)

结果:

{'a': 1, 'b': 2, 'c': 3}

 

分为两种用法:

1.定义函数时的应用,把传进来的参数放在元组中,注意:如果你传进来一个列表[1,2,3,4,5],print(args )后你会得到元组([1,2,3,4,5], )而不是元组(1,2,3,4,5),它并不会迭代的添加,所以for循环的时候只能循环1个数。

def f(*w):
    print(w)

l=[1,2,3,4]
f(l)

结果:

([1, 2, 3, 4],)

2.调用函数时使用,把传进来的迭代的参数拆开也就是加上*号,这也就是所谓的解包(Unpacking)

def f(*w):
    print(w)

l=[1,2,3,4]
f(*l)

结果:

(1, 2, 3, 4)

 

解包:把序列或映射中的每个元素提取出来。注意*后面跟序列,**后面跟映射。

打包: *args 或**kwargs把*解包传进来的值,打包成一个元组或字典.

例子:

l=[1,2,3,4,5]
print("list",*l)

d = {"hello": "world", "python": "rocks"}
print("dic1",*d)
print({**d}["python"])

结果:

list 1 2 3 4 5
dic1 hello python
rocks

 

谓的解包(Unpacking)实际上可以看做是去掉()的元组或者是去掉{}的字典。这一语法也提供了一个更加 Pythonic 地合并字典的方法:

user = {'name': "Trey", 'website': "http://treyhunner.com"}
defaults = {'name': "Anonymous User", 'page_name': "Profile Page"}

print({**defaults, **user})

 

{'page_name': 'Profile Page', 'name': 'Trey', 'website': 'http://treyhunner.com'

 

范例要求:写一个函数用来模拟len()的用法:

加*的情况:

 
  
def my_len(*args):
print("*args1",*args)
count=0
for i in args:
print("*args2",args)
count+=1
print(count)
my_len(*[1,2,3,4])
 

结果:

*args1 1 2 3 4               其实这里是一个元组(1,2,3,4)
*args2 (1, 2, 3, 4)
*args2 (1, 2, 3, 4)
*args2 (1, 2, 3, 4)
*args2 (1, 2, 3, 4)
4

不加*的情况:

def my_len(*args):
    print("*args",*args)
    count=0
    for i in args:
        print("*args",args)
        count+=1
    print(count)
my_len([1,2,3,4])

结果:

 
  

*args [1, 2, 3, 4]    其实这里得到的是一个元组([1, 2, 3, 4] ,)
*args ([1, 2, 3, 4],)
1

 
 

**kwargs: 接收所有按关键字传的参数。返回的是一个字典。注意在函数中用的时候不用加**,只需要kargs.

 命名空间

我们给这个“存放名字与值的关系”的空间起了一个名字——叫做命名空间

代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间,在函数的运行中开辟的临时的空间叫做局部命名空间, 内边的东西只能在局部使用

命名空间的本质:存放名字与值的绑定关系的一个区域

局部命名空间(局部变量):当函数运行起来时创建的存放函数中变量和值关系的空间。

全局命名空间(全局变量):存放定义在函数外边的的变量和函数名的空间。这个全局命名空间必须在调用函数()的前面出现,否则就不是一个全局变量,会报错。

内置命名空间:存放python解释器刚启动就能运行的变量和函数名的空间。不用你自己定义,直接就能用,比如len(),int(),但是import os 不是内置命名函数

各个变量的加载顺序; python解释器运行起来》内置变量》全局变量》局部变量(在调用函数的时候产生,并且随着调用的结束而消失)。

作用域

作用域:作用范围。

全局作用域:内置变量和全局变量的使用的区域叫做全局作用域 也就是可以在全局使用.。

局部作用域:局部变量可以使用的区域仅能在局部使用。

注意:全局变量不可以使用局部变量,局部变量可以使用全局变量,但是不能修改全局变量(后边这句话有歧义)。

如果你传入的参数对象或引用的全局变量是可变对象:列表,字典,如果参数在函数体内被修改(包括添加删除更新),那么全局变量也会被修改。
如果你传入的参数对象或引用的全局变量是不可变的对象:数字,元组,字符串。那么源对象是不会改变的

 例子1:

d = [2,3]
def f():
    d.append(66)
f()
print(d)

结果:

[2, 3, 66]

例子二:

dic = [2,3]
def f(d):
    d.append(66)
f(dic)
print(dic)

结果:

[2, 3, 66]

列子3

dic = 5
def f(d):
    d = 6
f(dic)
print(dic)

结果:

 5

 

 

 

局部作用域还可以嵌套更小的局部作用域。

作用域链:小范围作用域可以使用大范围的作用域,但是作用域链是单向的。

如何用一个全局变量函数调用一个局部变量函数? 

运用函数嵌套可以解决这个问题,看范例

范例一

 

def func1():
    def func2():
        n=8
        print(n)
    func2()
func1()                   #全局函数来调用局部变量

 

结果;

8

 globals():显示保存在全局作用域中的变量名和值。不管位置在哪里。

locals():local中的内容会根据它的位置来决定作用域中的内容,在局部作用域时,显示局部作用域中的变量名和值,在全局作用域中等于globasl。

范例

n=1
m=10
def func():
    a=10
    b=20
    print("locals",locals())
print("globals",globals())

func()

 

结果:

globals {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002015AEBB278>, 

'__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__':

'C:/Users/stickerzhang/PycharmProjects/untitled3/text1/tt/text2.py', '__cached__': None, 'foo': <function foo at 0x000002015AF8E488>,
'outer': <function outer at 0x000002015AF8E510>, 'n': 1, 'm': 10, 'func': <function func at 0x000002015AF8E7B8>}
locals {
'b': 20, 'a': 10}

 

范例二:

n=1
m=10
def func():
    a=10
    b=20
    print("globals",globals())
print("global",locals())
func()

结果:

globals '__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000014D5456A1D0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/Users/张守业/PycharmProjects/untitled/day9/global.py', '__cached__': None, 'n': 1, 'm': 10, 'func': <function func at 0x0000014D54486048>}
locals {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000014D5456A1D0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:/Users/张守业/PycharmProjects/untitled/day9/global.py', '__cached__': None, 'n': 1, 'm': 10, 'func': <function func at 0x0000014D54486048>}

global:我们知道在局部作用域中可以使用全局作用域中的变量和值,但是不能修改,如果要修改的话要用,global声明变量的作用域为全局作用域。注意这里的global修改的是全局的变量,不是局部的。

n=4
def f():
    global n
    n=9
f()
print(n)

结果:

 9

例子二:

n =0
def
f(): n=5 def f2(): global n n=n+1 f2() print('内层的',n) f() print('最外层的',n)

结果:

内层的 5  #没有修改最外层局部的n
最外层的 1 #修改的是全局的n

那如果要修改局部的n怎么,只能用nonlocal函数

nonlocal:闭包函数修改嵌套函数外边的函数中的变量值。python3中新添加的功能。

def f():
    n=5
    def f2():
        n=n+1
    f2()
    print(’外层的',n)

f()

 

结果:

会报错

 解决方法:

def f():
    n=5
    def f2():
        nonlocal n
        n=n+1
    f2()
    print('内层的',n)

f()

结果:

内层的 6

 

 

 

函数是第一类对象:

第一类对象共有的特征:

1.函数名可以赋值给别的变量。

2.函数可以作为一个函数的参数。

3.函数可以作为一个函数的返回值

4.函数可以作为一个数据结构的元素。

范例:

def func():
    print("in the func")
    return 10
def func2(arg):
    print("arg",arg()) ###打印一个函数也是对一个函数的调用
    return arg
f=func2(func)

结果:

in the func
arg 10

 

转载于:https://www.cnblogs.com/sticker0726/p/7762954.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值