Self-study Python Fish-C Note11 P42to44

函数 (part 1)

本节主要将定义函数,以及函数的各种类型的参数细节
函数的主要作用就是打包代码以,最大程度的实现代码的重用,并将不同功能的代码进行封装,分解来降低结构的复杂度,提高可读性。

创建和调用函数

# 创建
def fun1():
    pass # 空语句,常用作占位符。在规划程序的功能时候常用。
# 调用
fun1() 

函数的返回值 return 语句

def div(x,y):
    if y == 0:
        return 'mistake'
    else:
        return x/y
div(4,2)
2.0

返回多个值

Python 将返回的多个值会以元组的形式打包。我们可以通过分别赋值来将返回值解包

def func1():
    return 1,2,3
a = func1()
print(a,type(a))
(1, 2, 3) <class 'tuple'>
x,y,z = func1() # 将返回值解包
print(x,y,z)
1 2 3

注意:只要执行了 return 语句,函数就会立刻马上进行返回,不会再处理函数后面的语句。
所以上面的例子也可以像下面这么写:

def div(x,y):
    if y == 0:
        return 'mistake'
    return x/y
a = div(4,0)
b = div(4,2)
print(a,b)
mistake 2.0

注意:如果一个函数我们没有通过 return 语句显示的返回内容, 函数也会在执行完函数体中所有语句后,返回一个 None

def func1():
    a = 1+2
b = func1()
print(b)
None

函数的参数

形式参数 与 实际参数

形参(parameter)是形式参数的简称,又名Formal parameter,是在定义函数时跟在函数名后圆括号里面的变量名。
实参(argument)是实际参数的简称,又名Actual parameter,是在调用函数时跟在函数名后圆括号里面的值。

# 这个例子里 (x, times) 是形参;('function',3) 是实参
def fun1(x, times):
    for i in range(3):
        print(f'this is a {x}')
fun1('function',3)
this is a function
this is a function
this is a function

位置参数 与 关键字参数

位置参数

位置参数(positional argument),又称为定位参数,是在编程语言中函数或子程序调用的一种参数类型。 它们是根据参数在参数列表中的位置(而非名称)来确定其值的。

def func1(x,y,z):
    return ''.join((x,y,z))
func1('a','b','c')
'abc'
func1('c','b','a') # 对于参数的调用者来说,要按照正确的顺序传递参数
'cba'
关键字参数

函数调用时,指定参数名称,称为关键字参数(keyword argument)(In computer programming, named parameters, named-parameter arguments, named arguments or keyword arguments refer to a computer language’s support for function calls to clearly associate each argument with a given parameter within the function call.)

func1(z='c',y='b',x='a') # 明确指定 'a' 是给到 x 这个参数
'abc'

注意:位置参数必须在关键字参数之前

func1('a','b',z='c')
# func1(x='c','b','a') 就会报错
'abc'

默认参数

默认参数指的是当函数调用中省略了实参时自动使用的一个值

def func1(x,y,z='ccccc'):
    return ''.join((x,y,z))
print(func1('a','b')) # 不传递第三个参数,使用默认值
print(func1('a','b','c')) # 传递第三个参数,覆盖默认值
abccccc
abc

注意:使用默认参数的话,必须放置在最后

###### 以下代码会报错:SyntaxError: non-default argument follows default argument
# def func1(x='aaa',y,z='ccccc'):
#     return ''.join((x,y,z))
def func1(y,x='aaa',z='ccccc'):
    return ''.join((x,y,z))
func1('b') # 这样就没问题了
'aaabccccc'

用法:/

作用:/左边的参数必须传递位置参数,而不能是关键字参数;而/右侧随意,既可以使用位置参数也可以关键字参数

# 看一下几个 BIF 的文档
help(abs)
# abs(x=1.5) 报错:TypeError: abs() takes no keyword arguments
Help on built-in function abs in module builtins:

abs(x, /)
    Return the absolute value of the argument.
help(sum)
Help on built-in function sum in module builtins:

sum(iterable, /, start=0)
    Return the sum of a 'start' value (default: 0) plus an iterable of numbers
    
    When the iterable is empty, return the start value.
    This function is intended specifically for use with numeric values and may
    reject non-numeric types.
# sum(iterable, /, start=0) 这里 左边的 iterable 必须是位置参数,而右边的 start 可以随意
print(sum([1,2,3],10))
print(sum([1,2,3],start=100))
16
106
# 我们也可以用 /
def func1(a,/,b,c):
    print(a,b,c)
func1(1,2,3)
# func1(a=1,2,3) 会报错:SyntaxError: positional argument follows keyword argument
1 2 3
func1(1,b=2,c=3)
1 2 3

用法:*

作用:*左边的参数既可以使用位置参数也可以关键字参数,而*右侧必须传递关键字参数,而不能是位置参数
(个人看法:这个*其实就是一个匿名的收集参数,后面不加参数名的话会被一起收进去)

def func1(a,*,b,c):
    print(a,b,c)
func1(1,b=2,c=3)
# func1(1,2,3) 会报错:TypeError: func1() takes 1 positional argument but 3 were given
1 2 3

收集参数

收集参数,就是说只指定一个参数,然后允许调用函数时传入任意数量的参数

通过 * 打包到元组中 (*args)
def func1(*ar):
    print('In total, we have {} arguments.'.format(len(ar)))
    print('the second argument is: {}.'.format(ar[1]))
    print(ar) # here we can see ar is a tuple
    print(type(ar))
    
func1(1,2,3,4,5)
In total, we have 5 arguments.
the second argument is: 2.
(1, 2, 3, 4, 5)
<class 'tuple'>

注意:如果在收集参数后面还要指定其他参数,那么在调用函数的时候,就必须要用关键字参数来指定后面的参数,否则python就会把实参纳入到收集参数中

def func1(*a,b,c):
    print(a,b,c)
func1(1,2,3,4,5,b='A',c=3)
# func1(1,2,3,4,5) 就会报错:TypeError: func1() missing 2 required keyword-only arguments: 'b' and 'c'
## 否则 (1,2,3,4,5) 都收集到 *a 里了
(1, 2, 3, 4, 5) A 3
# 前文我们聊到 * 可以用作让 * 后面的参数必须是关键字参数, 如:
def func1(a,*,b,c):
    print(a,b,c)
func1(1,b=2,c=3) # 这里就不能 func1(1,2,3)
print('-'*30)
# 其实这个星号就是一个匿名的收集参数,使得后面的必须使用关键字参数
def func1(a,*no_name,b,c):
    print(a,b,c)
    print(no_name)
func1(1,2,3,4,5,b='A',c='1')
1 2 3
------------------------------
1 A 1
(2, 3, 4, 5)
通过 ** 打包到字典中 (**kwargs)

此时我们传递参数必须要使用关键字参数,因为要打包给字典,= 左边传给键,= 右边传给值。

def func1(**kwa):
    print(kwa)
func1(a=1,b=2,c=3)
{'a': 1, 'b': 2, 'c': 3}

混合使用:

def func1(a,*b,**c):
    print(a)
    print(b)
    print(c)
func1(1,2,3,4,5,x=6,b=7,c=8)
1
(2, 3, 4, 5)
{'x': 6, 'b': 7, 'c': 8}
# 内置方法 混合使用的例子
help(str.format)
Help on method_descriptor:

format(...)
    S.format(*args, **kwargs) -> str
    
    Return a formatted version of S, using substitutions from args and kwargs.
    The substitutions are identified by braces ('{' and '}').
解包参数

描述: *** 不仅可以在函数定义的时候使用来打包,在函数调用的时候,可以用来解包。即在形参上使用用于参数的打包,在实参上使用用于参数的解包。

a = (1,2,3,4)
def func1(x,y,z,t):
    print(x,y,z,t)
# 此时 func1(a) 会报错,因为需要四个参数却给了1个元组,一个参数
# 此时就要用 * 来解包
func1(*a)
1 2 3 4
a = {'x':1,'y':2,'z':3,'t':'A'}
# func1(*a) 此时这样传不可以,需要 ** 来解包成 关键字参数
func1(*a)
func1(**a)
x y z t
1 2 3 A
# 注意:
a = {'x':1,'y':2,'z':3,'t':'A','m':0,"n":9}
# func1(**a) 此时这样会报错:TypeError: func1() got an unexpected keyword argument 'm'



附言:
题目:Self-study Python Fish-C Note-11 P42-P44
本文为自学B站上鱼C的python课程随手做的笔记。一些概念和例子我个人为更好的理解做了些查询和补充
因本人水平有限,如有任何问题,欢迎大家批评指正!
原视频链接:https://www.bilibili.com/video/BV1c4411e77t?p=8
首先,需要了解芯片FT61F14x的GPIO口和SPI口的定义和使用方法。 GPIO口的定义可以在芯片的数据手册中查看,一般包括GPIO口的数量、输入输出状态、上拉/下拉电阻、中断等信息。SPI口的定义也可以在数据手册中查看,一般包括时钟、数据、使能、模式等信息。 接下来,可以按照以下步骤编写433通信程序: 1. 初始化GPIO口和SPI口,并设置其状态为输出和输入。 2. 配置SPI口的时钟、数据、使能和模式等参数。 3. 使用SPI口发送数据,并等待接收数据。 4. 根据接收到的数据进行处理并做出相应的响应。 下面是一个简单的示例代码: ```c #include <stdint.h> #include "FT61F14x.h" #define SPI_CS_PIN P40 #define SPI_CLK_PIN P41 #define SPI_MISO_PIN P42 #define SPI_MOSI_PIN P43 void spi_init(void) { /* 初始化SPI口 */ SPI_CS_PIN = 1; // 设置SPI片选引脚为高电平 SPI_CLK_PIN = 0; // 设置SPI时钟引脚为低电平 SPI_MOSI_PIN = 0; // 设置SPI数据输出引脚为低电平 SPI_MISO_PIN = 1; // 设置SPI数据输入引脚为高电平 } void spi_send(uint8_t data) { uint8_t i; SPI_CS_PIN = 0; // 使能SPI片选引脚 /* 发送8位数据 */ for (i = 0; i < 8; i++) { SPI_CLK_PIN = 0; // 低电平时钟,准备发送数据 SPI_MOSI_PIN = (data >> (7 - i)) & 0x01; // 发送数据的最高位 SPI_CLK_PIN = 1; // 高电平时钟,发送数据 } SPI_CS_PIN = 1; // 禁用SPI片选引脚 } uint8_t spi_receive(void) { uint8_t i, data = 0; SPI_CS_PIN = 0; // 使能SPI片选引脚 /* 接收8位数据 */ for (i = 0; i < 8; i++) { SPI_CLK_PIN = 0; // 低电平时钟,准备接收数据 data |= (SPI_MISO_PIN << (7 - i)); // 接收数据的最高位 SPI_CLK_PIN = 1; // 高电平时钟,接收数据 } SPI_CS_PIN = 1; // 禁用SPI片选引脚 return data; } void main(void) { uint8_t data; spi_init(); // 初始化SPI口 while (1) { spi_send(0xAA); // 发送数据 data = spi_receive(); // 接收数据 /* 根据接收到的数据进行处理 */ switch (data) { case 0x01: /* 处理数据 */ break; case 0x02: /* 处理数据 */ break; default: /* 处理数据 */ break; } } } ``` 需要注意的是,这只是一个简单的示例代码,实际开发中需要根据具体的需求进行修改和完善。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值