函数(一)

基本定义

一个程序的运行经常性伴随着函数, 所以函数可以理解为一段子程序或者子过程

函数的参数

形参

定义函数时候指定调用函数时候需要传递的参数

实参

调用函数时候传递的参数

位置参数

形参的一种, 实参传递给函数时候,根据形参的位置进行传递

默认参数

形参的一种, 函数在定义时候, 指定形参的值, 函数在调用时候, 如果实参传递了数据就使用实参传递的数据,否则就是用定义时候定义的这个值, 这个值又叫默认值

关键字参数

通过变量赋值的方式对函数进行传参

def Test(x,y)
	print(x,y)
  
Test(x=1, y=2)

非固定参数

形参的一种, *args, **kwargs

*args

实参传递的值就是单列容器打散后的值, 就是直接传值, 最后如果没有参数接收, 就有这个参数接收, 用元组的方式保存, 传值方式和位置参数的传值是一样的

**kwargs

实参传递的值就是双列容器打散后的值, 只有字典才是双列容器, 最后如果没有关键字参数接收, 则全部存入kwargs中, 传值方式和关键字传参一样

def Test(name,*args,**kwargs):
    print(name,args,kwargs)

Test('周泽SB','说得对',age=88, sex='not knownd')

函数的返回值和作用域

返回值

函数外部的代码想要获得函数的执行结果,则在函数里面用return语句来定义

  • 函数在执行过程中只要遇到return语句, 就会停止执行并返回结果
  • 如果未在函数中通过return语句来定义返回值, 则函数默认返回值就是None
  • 在函数中return多个值, 在函数外部拿到的时候, 这些值会以一个元组的形式呈现

全局与局部变量

局部变量只能够在函数内部调用

全局变量在程序的任何位置都可以被调用

函数内部在调用变量的时候,先找局部变量,再找全局变量

name='周泽SB' # 全局变量

def Test():
    global name  # 将变量name作为全局变量(不推荐使用)
    name='炮王' # 局部变量
    print(name)
    print(locals())  # 查看局部变量(函数内的变量)
    print(globals())  # 查看全局变量

Test() # 炮王
print(name)  # 周泽SB

传递列表,字典产生的现象

函数内如果直接调用全局变量, 则可以调用全局变量的一切的属性和方法

ls = ['周泽SB', '胡鸿鹏SB']
dic = {'name': "周泽SB", 'age': 87, 'hobby': '大保健'}

def Test(ls,dic):
    ls.append('罗文SB')  # ls是全局变量, 函数内调用全局变量ls并执行它的方法
    dic['desc']='为老不尊' # dic是全局变量, 函数内调用全局变量ls并执行它的方法
    return ls,dic

return_get=Test(ls,dic)

# 打印的结果一模一样
print(return_get)
print(ls,dic)

嵌套&匿名&高阶

嵌套函数

在函数内定义函数并调用这个函数, 只有在外层函数调用时候, 内层函数才会变得有意义

name='周泽SB'
def Test():
    name='炮王'
    def inner():
        name='周泽被绿了'
        print('第三层打印',name)

    inner()
    print('第二层打印',name)

Test()
print('第一层打印',name)

匿名函数

不需要指定函数的名字

一般不会写太复杂的语法, 能写的最复杂的也只是诸如三元运算符之类

calc_lambda = lambda x, y: x ** y  # 定义匿名函数
res_lambda = calc_lambda(2, 3)  # 调用匿名函数
print(res_lambda)  # 打印匿名函数的返回值
  • 上面的功能定义成有名函数
def calc(x, y):
    return x ** y

res = calc(2, 3)
print(res)

与map函数配合使用

map函数的用法

map(func, *iterables) --> map object
def calc(x):
    return x**2

res=map(calc,[1,2,3,4])
print(list(res))
  • 与匿名函数连用
res = map(lambda x: x ** 2, [1, 2, 3, 4])
print(list(res))
  • 匿名函数使用三元表达式
res = map(lambda x: x ** 2 if x > 10 else x ** 3, [1, 2, 3, 4,12])
print(list(res))

高阶函数

就是返回一个函数名的函数就叫高阶函数

  1. 接收一个或多个函数作为输入
  2. 返回的是输入的一个或多个函数的返回值
def get_abs(num):
    return int(str(num).strip('-'))

def add(x,y,func):  # 接收函数名作为输入
    return func(x)+func(y)  # 返回输入的函数的返回值

res=add(-130,-5,get_abs)
print(res)
  • 练习 写一个余数计算器

    def get_abs(num):
        return int(str(num).strip('-'))
    
    def add(x,y,func):
        return func(x)%func(y)
    
    res=add(-7,-6,get_abs)
    print(res)
    

函数的递归

  1. 必须要有一个明确的结束条件
  2. 每次递归,问题的规模会越来越小,离结果会越来越近
  3. 递归效率不高,递归层次过多会导致栈溢出, 会占用更多内存, 影响程序性能,所以python解释器默认加了1000层的递归限制

  • 将 100这个数字每次都除以2, 一直到不能除
n = 100

while n > 0:
    n = n // 2
    print(n)
  • 通过函数来实现
def calc(n):
    print(n)
    if n > 0:
        n = n // 2
        calc(n)
    print(n)


calc(100)

内置函数

abs

取绝对值

bin

返回整数的二进制格式( 将十进制转成二进制 ), 输出结果以0b开头

>>> bin(10)
'0b1010'
>>> bin(100)
'0b1100100'
>>> bin(1000)
'0b1111101000'

hex

返回一个10进制的16进制表示形式, 以0x开头

>>> hex(10)
'0xa'
>>> hex(100)
'0x64'

oct

返回一个10进制的8进制表示形式, 以0o开头

>>> oct(10)
'0o12'

bool

返回一个数据结构是True 或者 False ,

0, None(空字符串, 空集合,空字典,空列表, 空元组)都为False, 其余都为True

>>> bool([])
False
>>> bool('')
False
>>> bool(())
False
>>> bool({})
False
>>> bool(0)
False
>>> bool(None)
False

>>> bool(1)
True
>>> bool('周泽SB')
True

all

可迭代对象中每个元素通过bool函数判断都为True, 最后结果为True, 否则是False

>>> test=[1,2,3,0]
>>> all(test)
False

>>> test2=[1,2,3]
>>> all(test2)
True

any

可迭代对象中每个元素通过bool函数判断只要有一个为True, 最后结果为True, 否则是False

>>> test3=[0,None,'']
>>> any(test3)
False

>>> test4=[1,2,0,None,'']
>>> any(test4)
True

bytearray

将字节变成容器对象, 可以修改数据

>>> str='周泽SB'       
>>> a=str.encode('gbk')
>>> a
b'\xd6\xdc\xd4\xf3SB'
>>> b=bytearray(a)
>>> b
bytearray(b'\xd6\xdc\xd4\xf3SB')
>>> b[0]
214
>>> b[1]
220
>>> b[2]
212
>>> b[3]
243
>>> b[4]
83
>>> b[5]
66
>>> b[1]=200
>>> b
bytearray(b'\xd6\xc8\xd4\xf3SB')
>>> b.decode('gbk')
'秩泽SB'

bytes

对字符串进行编码

>>> test='周泽大炮'
>>> byte(test,'gbk')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'byte' is not defined
>>> bytes(test,'gbk')
b'\xd6\xdc\xd4\xf3\xb4\xf3\xc5\xda'
>>> test.encode('gbk')
b'\xd6\xdc\xd4\xf3\xb4\xf3\xc5\xda'

callable

用于检查一个对象是否是可调用的。如果返回 True,object 仍然可能调用失败;但如果返回 False,调用对象 object 绝对不会成功。

对于函数、方法、lambda 函式、 类以及实现了 **_call_ **方法的类实例, 它都返回 True。

>>> a=1
>>> callable(a)
False


>>> def add(a,b):
...     return a+b
... 
>>> callable(add)  # # 函数返回 True
True

>>> class A(object):
...     def method(self):
...             return 0
... 
>>> callable(A)  # 类返回 True
True
>>> a=A()
>>> callable(a)  # 没有实现 __call__, 返回 False
False

>>> class B(object):
...     def __call__(self):
...             return 0
... 
>>> callable(B)
True
>>> b=B()
>>> callable(b)  # 实现 __call__, 返回 True
True

chr

返回一个数字对应的ascii字符

>>> chr(65)
'A'
>>> chr(90)
'Z'

>>> chr(97)
'a'
>>> chr(122)
'z'

dict

生成一个空字典

>>> dic=dict()
>>> dic
{}

dir

显示对象的所有的可调用属性

>>> test=[1,2,3]
>>> test.
test.append(  test.count(   test.insert(  test.reverse(
test.clear(   test.extend(  test.pop(     test.sort(   
test.copy(    test.index(   test.remove( 
>>> dir(test)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

divmod

返回除法的商和余数

>>> divmod(4,3)
(1, 1)
>>> divmod(10,3)
(3, 1)

enumerate

返回列表的索引和元素

>>> a=['周泽SB','胡鸿鹏SB']
>>> enumerate(a)
<enumerate object at 0x10d6c0f78>
>>> list(enumerate(a))
[(0, '周泽SB'), (1, '胡鸿鹏SB')]

eval

把字符串形式的list,dict,set,tuple 再转换成原有的数据类型

a = ['周泽SB', '胡鸿鹏SB']
f = open('eval_test', 'w', encoding='utf-8')
f.write(str(a))
f.close()

f2 = open('eval_test', 'r', encoding='utf-8')
res = f2.read()
f2.close()
print(type(res))  # <class 'str'>

ls_res = eval(res)
print(type(ls_res))  # <class 'list'>

exec

把字符串格式的代码,进行转义并执行

>>> exec("print('周泽SB')")
周泽SB

filter

def Test(x):
    return x > 10  # 返回的是True或者False


res = filter(Test, [1, 3, 5, 44, 33])
print(list(res))

# 或者可以用匿名函数
>>> res=filter(lambda x:x>10,[1,44,22,3])
>>> list(res)
[44, 22]

frozenset

把一个集合变成不可修改的数据类型

>>> a={1,2}
>>> a.add(4)
>>> a
{1, 2, 4}
>>> b=frozenset(a)
>>> b.add(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'frozenset' object has no attribute 'add'
>>> b
frozenset({1, 2, 4})

globals

打印全局作用域里所有变量的信息

>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'test': [1, 2, 3], 'test2': [1, 2, 3], 'test3': [0, None, ''], 'test4': [1, 2, 0, None, ''], 'str': '周泽SB', 'a': {1, 2, 4, 6}, 'b': frozenset({1, 2, 4}), 'add': <function add at 0x10d6b3a60>, 'A': <class '__main__.A'>, 'B': <class '__main__.B'>, 'dic': {}, 'res': <filter object at 0x10d6b1f60>}

id

查看对象的内存地址

>>> a
{1, 2, 4, 6}
>>> id(a)
4518231624

isinstance

判断一个数据结构的类型

>>> b
frozenset({1, 2, 4})
>>> isinstance(b,frozenset)
True
>>> isinstance(b,list)
False

map

会根据提供的函数对指定序列做映射

>>> map(lambda x:x**2,[2,3,4])
<map object at 0x10d6b1e48>
>>> list(map(lambda x:x**2,[2,3,4]))
[4, 9, 16]

max

求最大值

>>> c=[33,545,232,3433]
>>> max(c)
3433

# 字符串比的是unicode中的对应的ascii里的数字的大小
>>> d=['周泽SB','胡鸿鹏SB']
>>> max(d)
'胡鸿鹏SB'
>>> ascii('周泽SB')
"'\\u5468\\u6cfdSB'"
>>> ascii('胡鸿鹏SB')
"'\\u80e1\\u9e3f\\u9e4fSB'"

min

求最小值

>>> d=['周泽SB','胡鸿鹏SB']
>>> min(d)
'周泽SB'

ord

返回ascii字符对应的十进制数

>>> ord('周')
21608
>>> ord('泽')
27901
>>> ord('S')
83
>>> ord('B')
66
>>> ord('胡')
32993
>>> ord('鸿')
40511
>>> ord('鹏')
40527

round

将一个小数四舍五入

>>> round(16.7,1)
16.7
>>> round(16.79,1)
16.8
>>> round(16.79,0)
17.0

zip

可以把2个或多个列表拼成一个列表

>>> a=[1,2,3]
>>> b=['周泽SB','胡鸿鹏SB']
>>> c=[33,44,55]
>>> zip(a,b)
<zip object at 0x10d6b8708>
>>> list(zip(a,b))
[(1, '周泽SB'), (2, '胡鸿鹏SB')]
>>> list(zip(a,b,c))
[(1, '周泽SB', 33), (2, '胡鸿鹏SB', 44)]

名称空间

存放名字的地方, 存放变量名与值这样一个关系的地方

分类

  • Locals

函数内部的名称空间, 一般包括函数的局部变量以及形式参数

  • enclosing function

在嵌套函数中外部函数的名称空间

  • globals

当前的模块空间, 或者全局空间, 在当前py文件的任何一个区域都是有效的

  • _builtins_

内置模块空间, python解释器启动就形成的一些名字空间, 通过 print(dir(_builtins_)) 来查看

查找顺序

Locals ---> enclosing function----> globals ---->_builtins_

level = 'L0'
dir = 11


def func():
    level = 'L1'
    dir = 22
    print(level, dir)

    def outer():
        level = 'L2'
        dir = '33'
        print(level, dir)

        def inner():
            level = 'L3'
            dir = '44'
            print(level, dir)

        inner()

    outer()


func()
posted @ 2019-09-29 17:14  cjw1219  阅读(378)  评论(0编辑  收藏  举报