Python 函数相关(一)

警告
本文最后更新于 2022-06-24,文中内容可能已过时。

1. 函数参数释义

  1. 必选参数
    函数定义时,定义了接收变量,那么在函数调用时就必须传递该参数值
  2. 默认参数
    在函数定义时,可为需要接受值的参数设置一个默认值,若函数调用时,该参数未传入值时,则使用默认值
  3. 可变参数
    • *args(关键字参数) : 可向函数中传递0个或多个参数(类似String…args),内部变量若为*args,结果将为元组,独立值将会顺序接收
    • **kwargs(命名关键字参数) : 可向函数中以键值对的形式传递0个或多个参数,内部变量若为**kwargs,结果将为字典,独立值将会顺序接收
  4. 组合参数
    用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数可组合使用,但参数传递顺序必须是: 必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

2. 函数即"变量"

3. 高阶函数

一个变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数

4. 嵌套函数

一个函数中可以包含另一个函数

5. 装饰器

  1. 示例代码1:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import time
def wrapper(func):
    def demo(*args, **kwargs):
        print("装饰器函数参数调用层 : ", time.time())
        res = func(*args, **kwargs)
        print("装饰器函数调用函数参数 : ", args, kwargs)
        return res
    return demo

@wrapper  # 注入?
# 函数即变量
#@test == {
#    test2=test(test1);
#调用
#    test2(11, a="01")
#}  == { test1 = test(test1) }
def calc(x, **kwargs):
    y = x * 10
    return "计算结果 y : %s" % y

calc(11, a="01")

print("=======================")

print(calc(11, a="01"))
  1. 示例代码2:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import time
def wrapper(ltype):
    print("装饰器参数传递层 wrapper: ",ltype)
    def demo(func):
        print("装饰器函数传递层 demo: ", ltype, func)
        def A(*args, **kwargs):
            print(time.time())
            print("装饰器调用函数参数传递层 A : ",  args, kwargs,ltype,func)
            res = func(*args,**kwargs)
            print("装饰器参数传递值 ltype :", ltype)
            return res
        return A
    return demo

@wrapper(ltype="Add")
def calc(x,y,name):
    z = x + y
    print(z)
    return z

print(calc(1, 2,name="123"))

6. 生成器

python中, 一边循环,一边计算的机制,就叫做生成器.
生成器不会第一时间将所有结果生成出来,他只会在循环到(调用)的时候才会生成需要的值,因此对于生成器产生的值是不允许切片的,另外,他每次调用也仅仅只保留当前正在被调用的这个值
生成器定义, 对于列表生成式将[] 替换为 (),创建出来的结果就是一个生成器 ,对于函数,包含了yelid变量(可用于模拟多线程)的就是一个生成器.

示例1:

1
2
3
4
5
6
# 列表创建
arr = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# 列表生成式创建 
arr = ( i*2 for i in range(10) )
# arr = <generator object <genexpr> at 0x7fa19c4b9570>
arr.__next__()

示例2:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 菲波拉契数列
# 0 1 1 2 3 5 8 13 21 34 ...
def fib(max):
    n, a , b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a+b

        n = n + 1
    return "None"

fib(10)
# fib(100) = <generator object fib at 0x7efc212447c8>

# fi = fib(10)
# print(next(fi))
# print(fi.__next__())

# 相关解释
# 1. yield 可以看成一个return但也有不同,当循环每次执行到此处的时候,他会返回结果值并暂停此次循环,以等待下一次的调用
#
# 2. 等式 a,b = b, a+b 并不等于
# {
#  a = b
#  b = a+b
# }
# 实际等于
# t = (a, a+b)
# a = t[0]
# b = t[1]
# 关于函数的return
# 由于生成生成器的调用必须使用__next__()来进行,而数据的生成大部分的时候都将会有最终的结果,而__next__()的时候是不会知道下一个值是否真正的存在,
# 此时__next__()就将会抛出一个程序异常,而这个异常的值就是return返回的值 .

生成器的调用, 在2.7中使用的是 next(arr), 3.x中使用的是arr.__next__(),不过next(arr) 在3.x同样也可以使用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
def work(name):
    print("%s 准备开始工作 !" %name)
    while True:
        things = yield name     # yield 后面可跟一个值,该值为send()调用后返回结果  
        print("%d 号文件已经收到了 , %s 打开了电脑, 开始工作 !" %(things,name))

import time
def people():
    w1 = work("用户1")      # 函数调用仅代表创出    w1 = work("用户1")      # 函数调用仅代表创出建一个生成器 
建一个生成器 
    w2 = work("用户2")
    w1.__next__()           # 只有在调用的时候才会进行第一次next,从而暂停到 yield 处 
    w2.__next__()
    for i in range(5):
        time.sleep(1)
        num = i+1
        print("%s 号工作任务文件来了 ! " % num)
        ww1 = w1.send(num)
        ww2 = w2.send(num)
        print("ww1: %s, ww2: %s" %(ww1,ww2))

people() 

7. 构造函数和析构函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 构造函数__init(self)__, 用于类被实例化时候使用,通常用于初始化实例变量 ,每个类必须有一个构造函数
# 析构函数__del(self)__, 一般用于在实例被销毁、释放的时候调用,通常用于一些收尾工作,比如数据库链接,打开的临时文件等
class Demo(object):
    c = 000
    def __init__(self,name):
        self.name = name

    def __del__(self):
        print("del: ",self.name, self.c)
        print("函数关闭")

d = Demo("Tname")
d.c = 111
d.c1 = 222
print(d.c, d.c1 , d.name)

8. 私有属性和私有方法

Python类中以__开头的变量为私有变量(属性),以__开头的函数为私有函数(方法),他们在类的外部不可查,不可被调用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Demo(object):
    __c = 111
    def __init__(self,name):
        self.name = name
        self.__age = 123

    def __b():
        print("hello")

d = Demo("Tname")

print(d.__c,  d.__age)
"""
Traceback (most recent call last):
  File "/home/cxd/Projects/node/Python/python.project/practice_script/1.py", line 13, in <module>
    print(d.__c,  d.__age)
AttributeError: 'Demo' object has no attribute '__c'
"""

d.__b()
"""
Traceback (most recent call last):
  File "/home/cxd/Projects/node/Python/python.project/practice_script/1.py", line 22, in <module>
    d.__b()
AttributeError: 'Demo' object has no attribute '__b'
"""

9. 迭代(Iterable)

从某个地方(比如一个列表)取出一个元素的过程。当我们使用一个循环来遍历某个东西时,这个过程本身就叫迭代

  1. 判断对象是否可迭代(对象):
1
2
3
4
5
6
7
8
9
from collections.abc import Iterable
print(isinstance('abc', Iterable))
# True
print(isinstance([], Iterable))
# True
print(isinstance(10, Iterable))
# False
print(isinstance((x for x in range(10)), Iterable))
# True

10. 迭代器(Iterator)

可以被next()函数调用并不断返回下一个值的对象被成为迭代器
生成器一定是一个迭代器,但迭代器不一定是一个生成器(生成器可能是一个列表或其他不能被next()的可迭代对象,)

  1. 判断对象是否是一个迭代器(对象):
1
2
3
4
5
6
7
from collections.abc import Iterator
isinstance([], Iterator)
# False
isinstance(iter([]), Iterator)  ## 通过函数 iter() 可将列表等迭代对象变成迭代器 
# True
isinstance((i for i in range(12)), Iterator)
# True

11. 内置函数

详见官方文档 : https://docs.python.org/zh-cn/3.7/library/functions.html

Map,Filter 和 Reduce https://eastlakeside.gitbooks.io/interpy-zh/content/Map_n_Filter/

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
# 判断可迭代对象内值是否全部为真(非0都为真),是:true 否:false
print(all([-1,0,1]))
# False

# 判断可迭代对象内值是否至少有一个为真,是:true 否:false
print(any([-1,0,1]))
# True

# 将10进制转换为二进制 
print(bin(1),bin(2),bin(4))
# 0b1 0b10 0b100

# 返回一个新的 bytes 数组。 bytearray 类是一个可变序列,包含范围为 0 <= x < 256 的整数。它有可变序列大部分常见的方法,见 可变序列类型 的描述;同时有 bytes 类型的大部分方法,参见 bytes 和 bytearray 操作。
{
    arr = bytearray("abc", encoding="utf-8")
    print("arr=%s, arr[0] = %s ,arr[1] = %s ,arr[2] = %s "  %( arr, arr[0], arr[1],arr[2]))
    # arr = bytearray(b'abc'), arr[0] = 97, arr[1] = 98, arr[2] = 99
    arr[0] = 100
    print("arr=%s, arr[0] = %s ,arr[1] = %s ,arr[2] = %s "  %( arr, arr[0], arr[1],arr[2]))
    # arr = bytearray(b'dbc'), arr[0] = 100, arr[1] = 98, arr[2] = 99
}

# 判断对象是否可被调用,是:true 否:false (即判断对象是否为一个函数或类或者说是是否可以在对象后面加上()进行调用)
print(callable(dir))        # dir 是一个函数,因此可以 dir()
# True 

# 将字符串转换为可执行的代码 (自动化 ?)
{
    str="""
    def demo():
        print("hello word")

    demo()
    """
    test = compile(str,'',"exec")
    exec(test)
    # hello word
}

# 从 iterable 对象中过滤出 function 中返回真的那些元素, (结果返回一个生成器) 
{
    # filter(function,iterable)
    res = filter(lambda n: n < 5, range(9))
    for i in res:
        print(i)
    # 0 1 2 3 4 
}

# 将 iterable 中的值通过 function 进行处理从而返回处理结果 , (结果返回一个生成器) 
{
    # filter(function,iterable)
    res = map(lambda n: n * 2, range(5))
    for i in res:
        print(i)
    # 0 2 4 6 8
}   
# 创建不可遍集合 
arr = frozenset([1,2,3,4,5]) 

# 获取可迭代对象的中的最大值
max([1,2,3,4,5])
# max(1,2,3,4,5)

# 将可迭代对象进行排序
{
    arr1 = {
        1:1,
        4:3,
        2:4,
        3:5,
        7:6,
        8:22,
        11:3,
        5:51
    }
    print(sorted(arr1))
    # [1, 2, 3, 4, 5, 7, 8, 11]

    print(sorted(arr1.items()))
    # [(1, 1), (2, 4), (3, 5), (4, 3), (5, 51), (7, 6), (8, 22), (11, 3)]

    print(sorted(arr1.items(),key=lambda x:x[1]))
    # 
    # [(1, 1), (4, 3), (11, 3), (2, 4), (3, 5), (7, 6), (8, 22), (5, 51)]


    arr2 = [1,5,2,3,8,9,4]
    print(sorted(arr2))
    # [1, 2, 3, 4, 5, 8, 9]
}

# zip 合并可迭代对象,以最小长度显示合并后的长度 
a = [1,2,3,4,5,6]
b = ['a','b','c','d']
c = zip(a,b)
for i in c :
    print(i)
    
# (1, 'a')
# (2, 'b')
# (3, 'c')
# (4, 'd')

12. 序列化与反序列化(pickle、json)