Python4

news2024/10/28 7:19:30

4. 更多控制流工具

除了刚介绍的 while 语句,Python 还用了一些别的。我们将在本章中遇到它们。

4.1. if 语句 

if elif else

if x<0:
    x = 0
    print('Negative changed to zero')
elif x==0:
    print(' zero')
else:
    print('More')

4.2. for 语句

Python 的 for 语句与 C 或 Pascal 中的不同。Python 的 for 语句不迭代算术递增数值(如 Pascal),或是给予用户定义迭代步骤和结束条件的能力(如 C),而是在列表或字符串等任意序列的元素上迭代,按它们在序列中出现的顺序。 例如

words = ['cat', 'window', 'defenestrate']
for x in words:
    print(x,len(x))

cat 3
window 6
defenestrate 12

很难正确地在迭代多项集的同时修改多项集的内容。更简单的方法是迭代多项集的副本或者创建新的多项集: 

# Create a sample collection
users = {'Hans': 'active', 'Éléonore': 'inactive', '景太郎': 'active'}

# Strategy:  Iterate over a copy
for x,y in users.copy().items():
    if y=='inactive' :
        del(users[x])
print(users)

 使用 copy().items() 的原因是防止在遍历字典时修改它。在 Python 中,如果直接遍历并修改字典(比如删除键值对),会导致运行错误,因为字典在遍历过程中不能被修改。

active_users = {}
for user, status in users.items():
    if status == 'active':
        active_users[user] = status
print(active_users)

4.3. range() 函数

内置函数 range() 用于生成等差数列:

for i in range(5):
    print(i)

步长正负都可以 

要按索引迭代序列,可以组合使用 range() 和 len(): 

print(list(range(5, 10)))
print(list(range(0, 10,3)))#3是步长
a = ['Mary', 'had', 'a', 'little', 'lamb']
for i in range(len(a)):
    print(i,a[i])

enumerate(iterablestart=0)

返回一个枚举对象。iterable 必须是一个序列,或 iterator,或其他支持迭代的对象。 enumerate() 返回的迭代器的 __next__() 方法返回一个元组,里面包含一个计数值(从 start 开始,默认为 0)和通过迭代 iterable 获得的值。

seasons = ['Spring', 'Summer', 'Fall', 'Winter']
print(list(enumerate(seasons)))
print(list(enumerate(seasons, start=1)))

[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]

range() 返回的对象是迭代对象

print(range(10))
print(sum(range(10)))

range(0, 10)
45 

 4.4. 循环中的 breakcontinue 语句及 else 子句:

break 语句将跳出最近的一层 for 或 while 循环。

for 或 while 循环可以包括 else 子句。

在 for 循环中,else 子句会在循环成功结束最后一次迭代之后执行。

在 while 循环中,它会在循环条件变为假值后执行。

无论哪种循环,如果因为 break 而结束,那么 else 子句就 不会 执行。

下面的搜索质数的 for 循环就是一个例子:

for n in range(2, 10):
    for x in range(2, n):
        if n % x == 0:
            print(n, 'equals', x, '*', n//x)
            break
    else:
        # else 子句属于 for 循环
        print(n, 'is a prime number')

 continue 语句,同样借鉴自 C 语言,以执行循环的下一次迭代来继续:

for num in range(2, 10):
    if num % 2 == 0:
        print("Found an even number", num)
        continue
    print("Found an odd number", num)

4.5. pass 语句

pass 语句不执行任何动作。语法上需要一个语句,但程序毋需执行任何动作时,可以使用该语句。例如:

while True:
    pass
class MyEmptyClass:
    pass
def initlog(*args):
    pass   # Remember to implement this!

pass 常用在构建函数、循环、类的初始阶段,使代码可以正常运行而不报错,等待后续完善。 

4.6. 定义函数

下列代码创建一个可以输出限定数值内的斐波那契数列函数 

def fib(n):    # write Fibonacci series up to n
    """Print a Fibonacci series up to n."""
#是 fib 函数的文档字符串(docstring),用于描述该函数的功能。
#它的主要作用是为代码提供说明和注释,使得代码更具可读性
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()

# Now call the function we just defined:
fib(2000)
help(fib)
#Python 的内置 help() 函数会读取文档字符串,便于使用者在不知道函数功能时查看其说明。

0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 
Help on function fib in module __main__:

fib(n)
    Print a Fibonacci series up to n.

def fib(n):
    result=[]
    a,b=0,1
    while a<n:
        result.append(a)
        a,b=b,a+b
    return result
f=fib
x=f(1000)
print(x)

4.7. 函数定义详解

函数定义支持可变数量的参数。这里列出三种可以组合使用的形式。

4.7.1. 默认值参数

为参数指定默认值是非常有用的方式。调用函数时,可以使用比定义时更少的参数,例如:

def ask_ok(prompt, retries=4, reminder='Please try again!'):
    while True:
        ok = input(prompt)
        if ok in ('y', 'ye', 'yes'):
            return True
        if ok in ('n', 'no', 'nop', 'nope'):
            return False
        retries = retries - 1
        if retries < 0:
            raise ValueError('invalid user response')
        print(reminder)

本例还使用了关键字 in ,用于确认序列中是否包含某个值 

默认值在 定义 作用域里的函数定义中求值,所以:

i = 5

def f(arg=i):
    print(arg)

i = 6
f()

重要警告: 默认值只计算一次。默认值为列表、字典或类实例等可变对象时,会产生与该规则不同的结果。例如,下面的函数会累积后续调用时传递的参数:

def f(a, L=[]):
    L.append(a)
    return L

print(f(1))
print(f(2))
print(f(3))

[1]
[1, 2]
[1, 2, 3] 

不想在后续调用之间共享默认值时,应以如下方式编写函数:

def f(a, L=None):
    if L==None:
        L=[]
    L.append(a)
    return L

print(f(1))
print(f(2))
print(f(3))

[1]
[2]
[3] 

4.7.2. 关键字参数 

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
    print("-- This parrot wouldn't", action, end=' ')
    print("if you put", voltage, "volts through it.")
    print("-- Lovely plumage, the", type)
    print("-- It's", state, "!")
parrot(1000)                                          # 1 positional argument
parrot(voltage=1000)                                  # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM')             # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000)             # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump')         # 3 positional arguments
parrot('a thousand', state='pushing up the daisies')  # 1 positional, 1 keyword

函数调用时,关键字参数必须跟在位置参数后面。所有传递的关键字参数都必须匹配一个函数接受的参数(比如,actor 不是函数 parrot 的有效参数),关键字参数的顺序并不重要。这也包括必选参数,(比如,parrot(voltage=1000) 也有效)。不能对同一个参数多次赋值,下面就是一个因此限制而失败的例子: 

def function(a):
    pass

function(0, a=0)

最后一个形参为 **name 形式时,接收一个字典(详见 映射类型 --- dict),该字典包含与函数中已定义形参对应之外的所有关键字参数。**name 形参可以与 *name 形参(下一小节介绍)组合使用(*name 必须在 **name 前面), *name 形参接收一个 元组,该元组包含形参列表之外的位置参数。例如,可以定义下面这样的函数:

def cheeseshop(kind, *arguments, **keywords):
    print("-- Do you have any", kind, "?")
    print("-- I'm sorry, we're all out of", kind)
    for arg in arguments:
        print(arg)
    print("-" * 40)
    for kw in keywords:
        print(kw, ":", keywords[kw])
  • *arguments 收集所有位置参数,允许传入任意数量的附加描述。
  • **keywords 收集所有关键字参数,允许为各种参数名称传递对应的值,以生成更详细的描述。

-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
shopkeeper : Michael Palin
client : John Cleese
sketch : Cheese Shop Sketch

4.7.3. 特殊参数 

默认情况下,参数可以按位置或显式关键字传递给 Python 函数。为了让代码易读、高效,最好限制参数的传递方式,这样,开发者只需查看函数定义,即可确定参数项是仅按位置、按位置或关键字,还是仅按关键字传递。

函数定义如下:

def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
      -----------    ----------     ----------
        |             |                  |
        |        Positional or keyword   |
        |                                - Keyword only
         -- Positional only

/ 和 * 是可选的。这些符号表明形参如何把参数值传递给函数:位置、位置或关键字、关键字。关键字形参也叫作命名形参。 

4.7.3.1. 位置或关键字参数

函数定义中未使用 / 和 * 时,参数可以按位置或关键字传递给函数。

4.7.3.2. 仅位置参数

此处再介绍一些细节,特定形参可以标记为 仅限位置仅限位置 时,形参的顺序很重要,且这些形参不能用关键字传递。仅限位置形参应放在 / (正斜杠)前。/ 用于在逻辑上分割仅限位置形参与其它形参。如果函数定义中没有 /,则表示没有仅限位置形参。

/ 后可以是 位置或关键字 或 仅限关键字 形参。

4.7.3.3. 仅限关键字参数

把形参标记为 仅限关键字,表明必须以关键字参数形式传递该形参,应在参数列表中第一个 仅限关键字 形参前添加 *

4.7.3.4. 函数示例

请看下面的函数定义示例,注意 / 和 * 标记:

def standard_arg(arg):
    print(arg)

def pos_only_arg(arg, /):
    print(arg)

def kwd_only_arg(*, arg):
    print(arg)

def combined_example(pos_only, /, standard, *, kwd_only):
    print(pos_only, standard, kwd_only)

第一个函数定义 standard_arg 是最常见的形式,对调用方式没有任何限制,可以按位置也可以按关键字传递参数

第二个函数 pos_only_arg 的函数定义中有 /,仅限使用位置形参

第三个函数 kwd_only_args 的函数定义通过 * 表明仅限关键字参数 

最后一个函数在同一个函数定义中,使用了全部三种调用惯例

下面的函数定义中,kwds 把 name 当作键,因此,可能与位置参数 name 产生潜在冲突:

def foo(name, **kwds):
    return 'name' in kwds
foo(1, **{'name': 2})

加上 / (仅限位置参数)后,就可以了。此时,函数定义把 name 当作位置参数,'name' 也可以作为关键字参数的键: 

def foo(name, /,**kwds):
    print(kwds)
    return 'name' in kwds
foo(1, **{'name': 2})

换句话说,仅限位置形参的名称可以在 **kwds 中使用,而不产生歧义 。

4.7.3.5. 小结

以下用例决定哪些形参可以用于函数定义:

def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):

说明:

  • 使用仅限位置形参,可以让用户无法使用形参名。形参名没有实际意义时,强制调用函数的实参顺序时,或同时接收位置形参和关键字时,这种方式很有用。

  • 当形参名有实际意义,且显式名称可以让函数定义更易理解时,阻止用户依赖传递实参的位置时,才使用关键字。

  • 对于 API,使用仅限位置形参,可以防止未来修改形参名时造成破坏性的 API 变动。

4.7.4. 任意实参列表

调用函数时,使用任意数量的实参是最少见的选项。这些实参包含在元组中(详见 元组和序列 )。在可变数量的实参之前,可能有若干个普通参数:

def write_multiple_items(file, separator, *args):
    file.write(separator.join(args))

variadic 参数用于采集传递给函数的所有剩余参数,因此,它们通常在形参列表的末尾。*args 形参后的任何形式参数只能是仅限关键字参数,即只能用作关键字参数,不能用作位置参数: 

def concat(*args, sep="/"):
    return sep.join(args)

concat("earth", "mars", "venus")

concat("earth", "mars", "venus", sep=".")

4.7.5. 解包实参列表

函数调用要求独立的位置参数,但实参在列表或元组里时,要执行相反的操作。例如,内置的 range() 函数要求独立的 start 和 stop 实参。如果这些参数不是独立的,则要在调用函数时,用 * 操作符把实参从列表或元组解包出来:

list(range(3, 6))            # normal call with separate arguments

args = [3, 6]
print(list(range(*args)))            # call with arguments unpacked from a list

[3, 4, 5] 

 同样,字典可以用 ** 操作符传递关键字参数

def parrot(voltage, state='a stiff', action='voom'):
    print("-- This parrot wouldn't", action, end=' ')
    print("if you put", voltage, "volts through it.", end=' ')
    print("E's", state, "!")

d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
parrot(**d)

4.7.6. Lambda 表达式

lambda 关键字用于创建小巧的匿名函数。lambda a, b: a+b 函数返回两个参数的和。Lambda 函数可用于任何需要函数对象的地方。在语法上,匿名函数只能是单个表达式。在语义上,它只是常规函数定义的语法糖。与嵌套函数定义一样,lambda 函数可以引用包含作用域中的变量:

def make_incrementor(n):
   return lambda x:x+n

f = make_incrementor(42)
print(f(1))

上例用 lambda 表达式返回函数。还可以把匿名函数用作传递的实参:

pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
pairs.sort(key=lambda pair: pair[1])
print(pairs)

pairs.sort(key=lambda pair: pair[1]) 使用 sort 方法对列表 pairs 进行排序。

  • key=lambda pair: pair[1] 指定排序的关键字为每个元组的第二个元素(即字符串部分)。
  • lambda pair: pair[1] 是一个匿名函数,它接收一个 pair 元组并返回 pair[1],用于比较排序。

[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]

4.7.7. 文档字符串

以下是文档字符串内容和格式的约定。

第一行应为对象用途的简短摘要。为保持简洁,不要在这里显式说明对象名或类型,因为可通过其他方式获取这些信息(除非该名称碰巧是描述函数操作的动词)。这一行应以大写字母开头,以句点结尾。

文档字符串为多行时,第二行应为空白行,在视觉上将摘要与其余描述分开。后面的行可包含若干段落,描述对象的调用约定、副作用等。

Python 解析器不会删除 Python 中多行字符串字面值的缩进,因此,文档处理工具应在必要时删除缩进。这项操作遵循以下约定:文档字符串第一行 之后 的第一个非空行决定了整个文档字符串的缩进量(第一行通常与字符串开头的引号相邻,其缩进在字符串中并不明显,因此,不能用第一行的缩进),然后,删除字符串中所有行开头处与此缩进“等价”的空白符。不能有比此缩进更少的行,但如果出现了缩进更少的行,应删除这些行的所有前导空白符。转化制表符后(通常为 8 个空格),应测试空白符的等效性。

下面是多行文档字符串的一个例子:

def my_function():
    """Do nothing, but document it.

    No, really, it doesn't do anything.
    """
    pass

print(my_function.__doc__)

4.7.8. 函数注解

函数注解 是可选的用户自定义函数类型的元数据完整信息(详见 PEP 3107 和 PEP 484 )。

标注 以字典的形式存放在函数的 __annotations__ 属性中,并且不会影响函数的任何其他部分。 形参标注的定义方式是在形参名后加冒号,后面跟一个表达式,该表达式会被求值为标注的值。 返回值标注的定义方式是加组合符号 ->,后面跟一个表达式,该标注位于形参列表和表示 def 语句结束的冒号之间。 下面的示例有一个必须的参数,一个可选的关键字参数以及返回值都带有相应的标注:

def f(ham: str, eggs: str = 'eggs') -> str:
    print("Annotations:", f.__annotations__)
    print("Arguments:", ham, eggs)
    return ham + ' and ' + eggs

f('spam')

4.8. 小插曲:编码风格 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2225278.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

游戏服务器被攻击有办法防护吗

游戏服务器受到攻击时比较常见的。就算是刚上线的游戏&#xff0c;都会有被攻击的时候。游戏服务器受到攻击的原因以及解决方案有哪些呢&#xff1f; 游戏服务器被攻击的原因有哪些呢&#xff1f; 1、常见的攻击&#xff0c;大部分来自于同行之间的恶意竞争&#xff0c;你的游…

Rust 力扣 - 3. 无重复字符的最长子串

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 我们需要记录当前子串的开始下标&#xff0c;一个哈希表记录字符和遍历过程中最后一次出现的索引 遍历字符串&#xff0c;如果在当前字符在哈希表中有记录&#xff0c;并且索引下标大于当前子串的开始下标&…

Lesson12---queue

Lesson12—queue 本篇博客介绍了cqueue的介绍使用以及模拟实现 文章目录 Lesson12---queue前言一、queue的成员函数1 queue2.empty3.size4.front5.back6.push7.pop 二、相关题目三、模拟实现完整代码 四、deque&#xff08;双端队列&#xff09;总结 前言 queue的文档:https:…

go高并发之路——本地缓存

一、使用场景 试想一个场景&#xff0c;有一个配置服务系统&#xff0c;里面存储着各种各样的配置&#xff0c;比如直播间的直播信息、点赞、签到、红包、带货等等。这些配置信息有两个特点&#xff1a; 1、并发量可能会特别特别大&#xff0c;试想一下&#xff0c;一个几十万…

CANopen中错误帧的制造和观测

本文讲述如何制造和观察CANopen中的错误帧&#xff08;Error frame&#xff09;&#xff0c;以Linux下的“VCAN0”为CAN接口来做测试&#xff0c;所以事先要先创建vcan0 一 制造错误帧 首先安装python CAN&#xff0c; pip3 install python-can然后参考python can的文档编写如…

Android View

前面我们了解了Android四大组件的工作流程&#xff0c;Android中还存在一个和四大组件地位相同的概念&#xff1a;View&#xff0c;用于向用户页面展示内容。我们经常使用的TextView、Button、ImageView控件等都继承于它&#xff0c;也会自定义View实现自定义效果。View类源码内…

2024CSP-J题目简析

扑克牌 1.题目大意&#xff1a;给定n张扑克牌和这n张扑克牌的花色和大小&#xff08;可能会有重复&#xff09;&#xff0c;需要输出还需要多少张牌才能凑齐一副扑克牌&#xff08;这里不考虑大小王&#xff0c;所以共52张&#xff09;。 2.思路概要&#xff1a;由于扑克牌会…

C++ | Leetcode C++题解之第513题找树左下角的值

题目&#xff1a; 题解&#xff1a; class Solution { public:int findBottomLeftValue(TreeNode* root) {int ret;queue<TreeNode *> q;q.push(root);while (!q.empty()) {auto p q.front();q.pop();if (p->right) {q.push(p->right);}if (p->left) {q.push(…

配置smaba (Linux与windows通信)

在Ubuntu上安装Samba是一个简单的过程。以下是详细的步骤&#xff0c;帮助你从安装到基本配置。 步骤1&#xff1a;更新软件包列表 首先&#xff0c;打开终端&#xff0c;确保你的软件包列表是最新的&#xff1a; sudo apt update 步骤2&#xff1a;安装 Samba 接下来…

若依学习 后端传过来的数据在控制台打印为空

导言: 在做若依二次开发时遇到个没见过的bug&#xff0c;用了一些时间排&#xff0c;发现有自己没学过的东西。所以记录一下。后端用的是c#的asp.net core 问题描述&#xff1a; 后端穿过来的有数据的参数(数组)roleIds在控制台打印为空 后端字段定义: 后端数据&#xff1a; 前…

centos-LAMP搭建与配置(论坛网站)

文章目录 LAMP简介搭建LAMP环境安装apache&#xff08;httpd&#xff09;安装mysql安装PHP安装php-mysql安装phpwind LAMP简介 LAMP是指一组通常一起使用来运行动态网站或者服务器的自由软件名称首字母缩写&#xff1a;Linux操作系统&#xff0c;网页服务器Apache&#xff0c;…

【LangChain系列3】【检索模块详解】

目录 前言一、LangChain1-1、介绍1-2、LangChain抽象出来的核心模块1-3、特点1-4、langchain解决的一些行业痛点1-5、安装 二、检索模块详解2-1、文档加载器2-1-1、Demo示例2-1-2、JSON加载2-1-3、CSV加载 2-2、文档转换器2-2-1、按字符进行拆分2-2-2、按代码分割2-2-3、Markdo…

arm 体系架构-过程调用标准AAPCS

一、什么是AAPCS&#xff1f; 旧时&#xff0c;ARM 过程调用标准叫做 APCS (ARM Procedure Call Standard)&#xff0c;Thumb的过程调用标准为 TPCS。如今这两种叫法已经废弃&#xff0c;统一称作 AAPCS (Procedure Call Standard for the ARM Architecture)。 AAPCS 是 ARM …

UE5之5.4 第三人称示例代码阅读

第三人称的代码相对第一人称少了很多&#xff0c;只有一个移动跳跃的能力 构造函数&#xff0c;添加角色的移动属性&#xff0c;限制了当controller移动角色不会乱转&#xff0c;然后创建了一个相机杆&#xff0c;创建了一个跟随相机&#xff0c;绑到相机杆上 然后在这个函数设…

用二分法查找有序容器的插入点

例子&#xff1a; int main() {vector<int> vec { 1,2,3,4,5,7,8,9 };auto n alg.find_binary_insert_pos(vec.begin(), vec.end(), 6);vec.insert(vec.begin() n, 6);_pn(vec);list<int> lst { 1,10,11,9,5 };for (auto& v : lst) {//添加不存在的元素au…

241024-Ragflow离线部署Docker-Rootless环境配置修改

A. 最终效果 B. 文件修改 docker-compose.yml include:- path: ./docker-compose-base.ymlenv_file: ./.envservices:ragflow:depends_on:mysql:condition: service_healthyes01:condition: service_healthyimage: ${RAGFLOW_IMAGE}container_name: ragflow-serverports:- ${…

D50【python 接口自动化学习】- python基础之类

day50 init方法 学习日期&#xff1a;20241027 学习目标&#xff1a;类 -- 64 init方法&#xff1a;如何为对象传递参数&#xff1f; 学习笔记&#xff1a; 魔术方法 init方法 class Klass(object):# 定义初始化方法&#xff0c;类实例化时自动进行初始化def __init__(self…

autMan框架的指令转换功能学习

以正则表达式为基础 一、基本用法【简单替换】 示例1&#xff1a; 匹配表达式&#xff1a;激活 结果表达式&#xff1a;咖啡码 效果&#xff1a;只要命令中包含“激活”这两个字&#xff0c;就会将命令中所有的“激活”替换为“咖啡码”&#xff0c;即你从后台看到收到的命令是…

leetcode-64-最小路径和

题解&#xff1a; 以题中矩阵为例&#xff1a; &#xff08;1&#xff09;走到grid[0][0]的最小距离就是起点grid[0][0]即dp[0][0]grid[0][0]; &#xff08;2&#xff09;走到grid[0][1]的最小距离&#xff1a;dp[0][1]grid[0][0]grid[0][1]; &#xff08;3&#xff09;走到…

《神经网络助力战场车辆及部件损毁识别与评估》

《神经网络助力战场车辆及部件损毁识别与评估》 一、战场车辆损毁评估的重要意义二、传统战场车辆损毁评估方法&#xff08;一&#xff09;视觉评估法&#xff08;二&#xff09;仪器检测技术 三、神经网络在战场车辆损毁评估中的应用案例&#xff08;一&#xff09;射击毁伤评…