创新互联Python教程:4.其他流程控制工具

4. 其他流程控制工具

除了上一章介绍的 while 语句,python 还支持其他语言中常见的流程控制语句,只是稍有不同。

磐安网站制作公司哪家好,找创新互联!从网页设计、网站建设、微信开发、APP开发、成都响应式网站建设等网站项目制作,到程序开发,运营维护。创新互联公司2013年成立到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选创新互联

4.1. if 语句

最让人耳熟能详的应该是 if 语句。例如:

 
 
 
 
  1. >>> x = int(input("Please enter an integer: "))
  2. Please enter an integer: 42
  3. >>> if x < 0:
  4. ... x = 0
  5. ... print('Negative changed to zero')
  6. ... elif x == 0:
  7. ... print('Zero')
  8. ... elif x == 1:
  9. ... print('Single')
  10. ... else:
  11. ... print('More')
  12. ...
  13. More

if 语句包含零个或多个 elif 子句及可选的 else 子句。关键字 ‘elif‘ 是 ‘else if’ 的缩写,适用于避免过多的缩进。ifelifelif … 序列可以当作其他语言中 switchcase 语句的替代品。

如果要把一个值与多个常量进行比较,或者检查特定类型或属性,match 语句更实用。详见 match 语句。

4.2. for 语句

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

 
 
 
 
  1. >>> # Measure some strings:
  2. ... words = ['cat', 'window', 'defenestrate']
  3. >>> for w in words:
  4. ... print(w, len(w))
  5. ...
  6. cat 3
  7. window 6
  8. defenestrate 12

遍历集合时修改集合的内容,会很容易生成错误的结果。因此不能直接进行循环,而是应遍历该集合的副本或创建新的集合:

 
 
 
 
  1. # Create a sample collection
  2. users = {'Hans': 'active', 'Éléonore': 'inactive', '景太郎': 'active'}
  3. # Strategy: Iterate over a copy
  4. for user, status in users.copy().items():
  5. if status == 'inactive':
  6. del users[user]
  7. # Strategy: Create a new collection
  8. active_users = {}
  9. for user, status in users.items():
  10. if status == 'active':
  11. active_users[user] = status

4.3. range() 函数

内置函数 range() 常用于遍历数字序列,该函数可以生成算术级数:

 
 
 
 
  1. >>> for i in range(5):
  2. ... print(i)
  3. ...
  4. 0
  5. 1
  6. 2
  7. 3
  8. 4

生成的序列不包含给定的终止数值;range(10) 生成 10 个值,这是一个长度为 10 的序列,其中的元素索引都是合法的。range 可以不从 0 开始,还可以按指定幅度递增(递增幅度称为 ‘步进’,支持负数):

 
 
 
 
  1. >>> list(range(5, 10))
  2. [5, 6, 7, 8, 9]
  3. >>> list(range(0, 10, 3))
  4. [0, 3, 6, 9]
  5. >>> list(range(-10, -100, -30))
  6. [-10, -40, -70]

range() 和 len() 组合在一起,可以按索引迭代序列:

 
 
 
 
  1. >>> a = ['Mary', 'had', 'a', 'little', 'lamb']
  2. >>> for i in range(len(a)):
  3. ... print(i, a[i])
  4. ...
  5. 0 Mary
  6. 1 had
  7. 2 a
  8. 3 little
  9. 4 lamb

不过,大多数情况下,enumerate() 函数更便捷,详见 循环的技巧 。

如果只输出 range,会出现意想不到的结果:

 
 
 
 
  1. >>> range(10)
  2. range(0, 10)

range() 返回对象的操作和列表很像,但其实这两种对象不是一回事。迭代时,该对象基于所需序列返回连续项,并没有生成真正的列表,从而节省了空间。

这种对象称为可迭代对象 iterable,函数或程序结构可通过该对象获取连续项,直到所有元素全部迭代完毕。for 语句就是这样的架构,sum() 是一种把可迭代对象作为参数的函数:

 
 
 
 
  1. >>> sum(range(4)) # 0 + 1 + 2 + 3
  2. 6

下文将介绍更多返回可迭代对象或把可迭代对象当作参数的函数。 在 数据结构 这一章节中,我们将讨论有关 list() 的更多细节。

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

break 语句和 C 中的类似,用于跳出最近的 for 或 while 循环。

循环语句支持 else 子句;for 循环中,可迭代对象中的元素全部循环完毕,或 while 循环的条件为假时,执行该子句;break 语句终止循环时,不执行该子句。 请看下面这个查找素数的循环示例:

 
 
 
 
  1. >>> for n in range(2, 10):
  2. ... for x in range(2, n):
  3. ... if n % x == 0:
  4. ... print(n, 'equals', x, '*', n//x)
  5. ... break
  6. ... else:
  7. ... # loop fell through without finding a factor
  8. ... print(n, 'is a prime number')
  9. ...
  10. 2 is a prime number
  11. 3 is a prime number
  12. 4 equals 2 * 2
  13. 5 is a prime number
  14. 6 equals 2 * 3
  15. 7 is a prime number
  16. 8 equals 2 * 4
  17. 9 equals 3 * 3

(没错,这段代码就是这么写。仔细看:else 子句属于 for 循环,不属于 if 语句。)

与 if 语句相比,循环的 else 子句更像 try 的 else 子句: try 的 else 子句在未触发异常时执行,循环的 else 子句则在未运行 break 时执行。try 语句和异常详见 异常的处理。

continue 语句也借鉴自 C 语言,表示继续执行循环的下一次迭代:

 
 
 
 
  1. >>> for num in range(2, 10):
  2. ... if num % 2 == 0:
  3. ... print("Found an even number", num)
  4. ... continue
  5. ... print("Found an odd number", num)
  6. ...
  7. Found an even number 2
  8. Found an odd number 3
  9. Found an even number 4
  10. Found an odd number 5
  11. Found an even number 6
  12. Found an odd number 7
  13. Found an even number 8
  14. Found an odd number 9

4.5. pass 语句

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

 
 
 
 
  1. >>> while True:
  2. ... pass # Busy-wait for keyboard interrupt (Ctrl+C)
  3. ...

下面这段代码创建了一个最小的类:

 
 
 
 
  1. >>> class MyEmptyClass:
  2. ... pass
  3. ...

pass 还可以用作函数或条件子句的占位符,让开发者聚焦更抽象的层次。此时,程序直接忽略 pass

 
 
 
 
  1. >>> def initlog(*args):
  2. ... pass # Remember to implement this!
  3. ...

4.6. match 语句

A match statement takes an expression and compares its value to successive patterns given as one or more case blocks. This is superficially similar to a switch statement in C, Java or JavaScript (and many other languages), but it’s more similar to pattern matching in languages like Rust or Haskell. Only the first pattern that matches gets executed and it can also extract components (sequence elements or object attributes) from the value into variables.

最简单的形式是将一个目标值与一个或多个字面值进行比较:

 
 
 
 
  1. def http_error(status):
  2. match status:
  3. case 400:
  4. return "Bad request"
  5. case 404:
  6. return "Not found"
  7. case 418:
  8. return "I'm a teapot"
  9. case _:
  10. return "Something's wrong with the internet"

注意最后一个代码块:“变量名” _ 被作为 通配符 并必定会匹配成功。 如果没有 case 语句匹配成功,则不会执行任何分支。

使用 | (“ or ”)在一个模式中可以组合多个字面值:

 
 
 
 
  1. case 401 | 403 | 404:
  2. return "Not allowed"

模式的形式类似解包赋值,并可被用于绑定变量:

 
 
 
 
  1. # point is an (x, y) tuple
  2. match point:
  3. case (0, 0):
  4. print("Origin")
  5. case (0, y):
  6. print(f"Y={y}")
  7. case (x, 0):
  8. print(f"X={x}")
  9. case (x, y):
  10. print(f"X={x}, Y={y}")
  11. case _:
  12. raise ValueError("Not a point")

请仔细研究此代码! 第一个模式有两个字面值,可以看作是上面所示字面值模式的扩展。但接下来的两个模式结合了一个字面值和一个变量,而变量 绑定 了一个来自目标的值(point)。第四个模式捕获了两个值,这使得它在概念上类似于解包赋值 (x, y) = point

如果使用类实现数据结构,可在类名后加一个类似于构造器的参数列表,这样做可以把属性放到变量里:

 
 
 
 
  1. class Point:
  2. x: int
  3. y: int
  4. def where_is(point):
  5. match point:
  6. case Point(x=0, y=0):
  7. print("Origin")
  8. case Point(x=0, y=y):
  9. print(f"Y={y}")
  10. case Point(x=x, y=0):
  11. print(f"X={x}")
  12. case Point():
  13. print("Somewhere else")
  14. case _:
  15. print("Not a point")

可在 dataclass 等支持属性排序的内置类中使用位置参数。还可在类中设置 __match_args__ 特殊属性为模式的属性定义指定位置。如果它被设为 (“x”, “y”),则以下模式均为等价的,并且都把 y 属性绑定到 var 变量:

 
 
 
 
  1. Point(1, var)
  2. Point(1, y=var)
  3. Point(x=1, y=var)
  4. Point(y=var, x=1)

读取模式的推荐方式是将它们看做是你会在赋值操作左侧放置的内容的扩展形式,以便理解各个变量将会被设置的值。 只有单独的名称(例如上面的 var)会被 match 语句所赋值。 带点号的名称 (例如 foo.bar)、属性名称(例如上面的 x=y=)或类名称(通过其后的 “(…)” 来识别,例如上面的 Point)都绝不会被赋值。

模式可以任意地嵌套。例如,如果有一个由点组成的短列表,则可使用如下方式进行匹配:

 
 
 
 
  1. match points:
  2. case []:
  3. print("No points")
  4. case [Point(0, 0)]:
  5. print("The origin")
  6. case [Point(x, y)]:
  7. print(f"Single point {x}, {y}")
  8. case [Point(0, y1), Point(0, y2)]:
  9. print(f"Two on the Y axis at {y1}, {y2}")
  10. case _:
  11. print("Something else")

为模式添加成为守护项的 if 子句。如果守护项的值为假,则 match 继续匹配下一个 case 语句块。注意,值的捕获发生在守护项被求值之前:

 
 
 
 
  1. match point:
  2. case Point(x, y) if x == y:
  3. print(f"Y=X at {x}")
  4. case Point(x, y):
  5. print(f"Not on the diagonal")

match 语句的其他特性:

  • 与解包赋值类似,元组和列表模式具有完全相同的含义,并且实际上能匹配任意序列。 但它们不能匹配迭代器或字符串。

  • 序列模式支持扩展解包操作:[x, y, *rest](x, y, *rest) 的作用类似于解包赋值。 在 * 之后的名称也可以为 _,因此,(x, y, *_) 可以匹配包含至少两个条目的序列,而不必绑定其余的条目。

  • 映射模式:{"bandwidth": b, "latency": l} 从字典中捕获 "bandwidth""latency" 的值。与序列模式不同,额外的键会被忽略。**rest 等解包操作也支持。但 **_ 是冗余的,不允许使用。

  • 使用 as 关键字可以捕获子模式:

       
       
       
       
    1. case (Point(x1, y1), Point(x2, y2) as p2): ...

    将把输入的第二个元素捕获为 p2 (只要输入是包含两个点的序列)

  • 大多数字面值是按相等性比较的,但是单例对象 True, FalseNone 则是按标识号比较的。

  • 模式可以使用命名常量。 这些命名常量必须为带点号的名称以防止它们被解读为捕获变量:

       
       
       
       
    1. from enum import Enum
    2. class Color(Enum):
    3. RED = 'red'
    4. GREEN = 'green'
    5. BLUE = 'blue'
    6. color = Color(input("Enter your choice of 'red', 'blue' or 'green': "))
    7. match color:
    8. case Color.RED:
    9. print("I see red!")
    10. case Color.GREEN:
    11. print("Grass is green")
    12. case Color.BLUE:
    13. print("I'm feeling the blues :(")

要获取更详细的说明和额外的示例,你可以参阅以教程格式撰写的 PEP 636。

4.7. 定义函数

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

 
 
 
 
  1. >>> def fib(n): # write Fibonacci series up to n
  2. ... """Print a Fibonacci series up to n."""
  3. ... a, b = 0, 1
  4. ... while a < n:
  5. ... print(a, end=' ')
  6. ... a, b = b, a+b
  7. ... print()
  8. ...
  9. >>> # Now call the function we just defined:
  10. ... fib(2000)
  11. 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

定义 函数使用关键字 def,后跟函数名与括号内的形参列表。函数语句从下一行开始,并且必须缩进。

函数内的第一条语句是字符串时,该字符串就是文档字符串,也称为 docstring,详见 文档字符串。利用文档字符串可以自动生成在线文档或打印版文档,还可以让开发者在浏览代码时直接查阅文档;Python 开发者最好养成在代码中加入文档字符串的好习惯。

函数在 执行 时使用函数局部变量符号表,所有函数变量赋值都存在局部符号表中;引用变量时,首先,在局部符号表里查找变量,然后,是外层函数局部符号表,再是全局符号表,最后是内置名称符号表。因此,尽管可以引用全局变量和外层函数的变量,但最好不要在函数内直接赋值(除非是 global 语句定义的全局变量,或 nonlocal 语句定义的外层函数变量)。

在调用函数时会将实际参数(实参)引入到被调用函数的局部符号表中;因此,实参是使用 按值调用 来传递的(其中的 始终是对象的 引用 而不是对象的值)。 1 当一个函数调用另外一个函数时,会为该调用创建一个新的局部符号表。

函数定义在当前符号表中把函数名与函数对象关联在一起。解释器把函数名指向的对象作为用户自定义函数。还可以使用其他名称指向同一个函数对象,并访问访该函数:

 
 
 
 
  1. >>> fib
  2. >>> f = fib
  3. >>> f(100)
  4. 0 1 1 2 3 5 8 13 21 34 55 89

fib 不返回值,因此,其他语言不把它当作函数,而是当作过程。事实上,没有 return 语句的函数也返回值,只不过这个值比较是 None (是一个内置名称)。一般来说,解释器不会输出单独的返回值 None ,如需查看该值,可以使用 print():

 
 
 
 
  1. >>> fib(0)
  2. >>> print(fib(0))
  3. None

编写不直接输出斐波那契数列运算结果,而是返回运算结果列表的函数也非常简单:

 
 
 
 
  1. >>> def fib2(n): # return Fibonacci series up to n
  2. ... """Return a list containing the Fibonacci series up to n."""
  3. ... result = []
  4. ... a, b = 0, 1
  5. ... while a < n:
  6. ... result.append(a) # see below
  7. ... a, b = b, a+b
  8. ... return result
  9. ...
  10. >>> f100 = fib2(100) # call it
  11. >>> f100 # write the result
  12. [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

本例也新引入了一些 Python 功能:

  • return 语句返回函数的值。return 语句不带表达式参数时,返回 None。函数执行完毕退出也返回 None

  • result.append(a) 语句调用了列表对象 result方法 。方法是“从属于”对象的函数,命名为 obj.methodnameobj 是对象(也可以是表达式),methodname 是对象类型定义的方法名。不同类型定义不同的方法,不同类型的方法名可以相同,且不会引起歧义。(用 可以自定义对象类型和方法,详见 类 )示例中的方法 append() 是为列表对象定义的,用于在列表末尾添加新元素。本例中,该方法相当于 result = result + [a] ,但更有效。

4.8. 函数定义详解

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

4.8.1. 默认值参数

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

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

该函数可以用以下方式调用:

  • 只给出必选实参:ask_ok('Do you really want to quit?')

  • 给出一个可选实参:ask_ok('OK to overwrite the file?', 2)

  • 给出所有实参:ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')

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

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

 
 
 
 
  1. i = 5
  2. def f(arg=i):
  3. print(arg)
  4. i = 6
  5. f()

上例输出的是 5

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

 
 
 
 
  1. def f(a, L=[]):
  2. L.append(a)
  3. return L
  4. print(f(1))
  5. print(f(2))
  6. print(f(3))

输出结果如下:

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

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

 
 
 
 
  1. def f(a, L=None):
  2. if L is None:
  3. L = []
  4. L.append(a)
  5. return L

4.8.2. 关键字参数

kwarg=value 形式的 关键字参数 也可以用于调用函数。函数示例如下:

 
 
 
 
  1. def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
  2. print("-- This parrot wouldn't", action, end=' ')
  3. print("if you put", voltage, "volts through it.")
  4. print("-- Lovely plumage, the", type)
  5. print("-- It's", state, "!")

该函数接受一个必选参数(voltage)和三个可选参数(state, actiontype)。该函数可用下列方式调用:

 
 
 
 
  1. parrot(1000) # 1 positional argument
  2. parrot(voltage=1000) # 1 keyword argument
  3. parrot(voltage=1000000, action='VOOOOOM') # 2 keyword arguments
  4. parrot(action='VOOOOOM', voltage=1000000) # 2 keyword arguments
  5. parrot('a million', 'bereft of life', 'jump') # 3 positional arguments
  6. parrot('a thousand', state='pushing up the daisies') # 1 positional, 1 keyword

以下调用函数的方式都无效:

 
 
 
 
  1. parrot() # required argument missing
  2. parrot(voltage=5.0, 'dead') # non-keyword argument after a keyword argument
  3. parrot(110, voltage=220) # duplicate value for the same argument
  4. parrot(actor='John Cleese') # unknown keyword argument

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

 
 
 
 
  1. >>> def function(a):
  2. ... pass
  3. ...
  4. >>> function(0, a=0)
  5. Traceback (most recent call last):
  6. File "", line 1, in
  7. TypeError: function() got multiple values for argument 'a'

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

 
 
 
 
  1. def cheeseshop(kind, *arguments, **keywords):
  2. print("-- Do you have any", kind, "?")
  3. print("-- I'm sorry, we're all out of", kind)
  4. for arg in arguments:
  5. print(arg)
  6. print("-" * 40)
  7. for kw in keywords:
  8. print(kw, ":", keywords[kw])

该函数可以用如下方式调用:

 
 
 
 
  1. cheeseshop("Limburger", "It's very runny, sir.",
  2. "It's really very, VERY runny, sir.",
  3. shopkeeper="Michael Palin",
  4. client="John Cleese",
  5. sketch="Cheese Shop Sketch")

输出结果如下:

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

注意,关键字参数在输出结果中的顺序与调用函数时的顺序一致。

4.8.3. 特殊参数

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

函数定义如下:

 
 
 
 
  1. def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
  2. ----------- ---------- ----------
  3. | | |
  4. | Positional or keyword |
  5. | - Keyword only
  6. -- Positional only

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

4.8.3.1. 位置或关键字参数

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

4.8.3.2. 仅位置参数

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

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

4.8.3.3. 仅限关键字参数

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

4.8.3.4. 函数示例

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

 
 
 
 
  1. >>> def standard_arg(arg):
  2. ... print(arg)
  3. ...
  4. >>> def pos_only_arg(arg, /):
  5. ... print(arg)
  6. ...
  7. >>> def kwd_only_arg(*, arg):
  8. ... print(arg)
  9. ...
  10. >>> def combined_example(pos_only, /, standard, *, kwd_only):
  11. ... print(pos_only, standard, kwd_only)

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

 
 
 
 
  1. >>> standard_arg(2)
  2. 2
  3. >>> standard_arg(arg=2)
  4. 2

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

 
 
 
 
  1. >>> pos_only_arg(1)
  2. 1
  3. >>> pos_only_arg(arg=1)
  4. Traceback (most recent call last):
  5. File "", line 1, in
  6. TypeError: pos_only_arg() got some positional-only arguments passed as keyword arguments: 'arg'

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

 
 
 
 
  1. >>> kwd_only_arg(3)
  2. Traceback (most recent call last):
  3. File "", line 1, in
  4. TypeError: kwd_only_arg() takes 0 positional arguments but 1 was given
  5. >>> kwd_only_arg(arg=3)
  6. 3

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

 
 
 
 
  1. >>> combined_example(1, 2, 3)
  2. Traceback (most recent call last):
  3. File "", line 1, in
  4. TypeError: combined_example() takes 2 positional arguments but 3 were given
  5. >>> combined_example(1, 2, kwd_only=3)
  6. 1 2 3
  7. >>> combined_example(1, standard=2, kwd_only=3)
  8. 1 2 3
  9. >>> combined_example(pos_only=1, standard=2, kwd_only=3)
  10. Traceback (most recent call last):
  11. File "", line 1, in
  12. TypeError: combined_example() got some positional-only arguments passed as keyword arguments: 'pos_only'

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

 
 
 
 
  1. def foo(

    名称栏目:创新互联Python教程:4.其他流程控制工具
    文章起源:http://www.shufengxianlan.com/qtweb/news11/515411.html

    网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

    广告

    声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联