(翻译)30天学习Python👨‍💻第六天——循环和函数

262 阅读6分钟

30天学习Python👨‍💻第六天——循环和函数

编写Python的乐趣应该是让我们看到短小、简洁、易读的代码,它们用少量清晰的代码表达了大量的操作——而不是用大量让读者厌烦得要死的琐碎代码。

Guido van Rossum

继续从上次的地方开始,我会继续探索循环,并写一些代码。然后我会进军编程中最重要的一部分——函数。在Python里我学到了函数、方法、文档字符串。最佳实践,以及作用域。我会以简洁易懂的方式进行解释。

继续我们的循环。

While循环

while循环

While循环是根据特定条件多次运行代码块的另一种方式。处理while循环时需要特别小心,一不小心就会出现无限循环,这会把我们的系统搞崩溃的。

hungry = True
while(hungry): # 总是为true,因此会不停的打印直到系统崩溃
  print('Give me something to eat!!')

但是while是非常有用的,它非常的容易书写并且容易阅读。我们只需要告诉编译器停止循环的条件。也可以使用break语句阻止循环执行并且跳出循环。另一种方式是使条件为falsy来停止执行。

hungry = True
while(hungry):
    print('Give me something to eat!!')
    break # 只打印一次,然后会停止循环
hungry = True
satisfaction = 0
while(satisfaction < 10):
  satisfaction += 1
  print('Give me something to eat!!') # 打印十次

while循环的另一个特点是它可以和else语句结合起来。

hungry = True
satisfaction = 0
while satisfaction < 10:
  satisfaction += 1
  print('Give me something to eat!!')
else:
    print('I am super satisfied now') # 条件为假时会打印一次

需要注意的是,如果break使用在while语句块中,else不会被执行

While和For循环的对比

当我们知道需要迭代的范围时,通常会用for循环。但是当循环条件比较复杂,又不知道迭代范围的时候,while就派上用场了。

while True:
  response_from_user = input('Enter some message. Enter bye to exit')
  if(response_from_user == 'bye'):
    break

除了break之外,还有另外两种语句:continuepasscontinue 不是跳出循环,而是继续迭代。pass不是很常用,但是有时可以作为占位符,在循环后继续执行语句。

编程练习

找出列表照中重复的邮件地址,并打印出来

email_list = ['roger@hey.com','michael@hey.com','roger@hey.com','prince@gmail.com']
duplicate_emails = []
for email in email_list:
  if email_list.count(email) > 1 and email not in duplicate_emails:
    duplicate_emails.append(email)
print(duplicate_emails)

这就是我解决这个问题的方法,可以把你的想法写在评论区。现在是时候切换到下一个主题了——函数。

函数

函数定义

函数是非常重要的概念,在所有的编程语言中都存在。函数允许我们定义一种行为(代码块),然后在遵循DRY(Don't repeat yourself)原则下可以多次执行。【译者注:DRY原则是指系统的每一个功能都应该有唯一的实现。如果多次遇到同样的问题,就应该抽象出一个共同的解决方法,而不要重复开发同样的功能】。到目前为止,我们已经使用了Python中的一些内置函数,比如printinputlen等。现在是时候我们自己创建了。

def blow_fire(): # 函数定义
  print('fire 🔥 🔥 🔥')

blow_fire() # 函数调用
blow_fire() # 它可以调用任意多次执行

参数

上面的函数很好但是有一些缺陷,它只能执行相同的动作。现在让我们给它传一些参数,使其更具扩展性,并且可以执行任意的动作。

def blower(name, emoji): # 形参
  print(f'{name} {emoji} {emoji} {emoji}')

blower('fire', '🔥') # 实参
blower('water', '🌊')

定义函数时,我们向它提供一些数据,并且根据这些数据执行动作,这些函数定义时规定传入的数据称为形参(函数定义时括号中的数据)。一个函数可以有任意数量的参数。当函数被调用时,实际接受的参数称作实参。

上面的参数也被称为条件参数,因为参数的位置顺序很重要。

def blower(name = 'fire', emoji = '🔥'): # 默认参数
  print(f'{name} {emoji} {emoji} {emoji}')

blower('fire', '🔥') # 实参
blower('water', '🌊')
blower() # fire 🔥 # 没有传入参数时,使用默认参数

返回值

return是Python中的一个关键字,它被用于从函数中返回值。要想使函数更有用,就需要函数执行表达式之后返回一些值。如果没有return语句或者return语句的表达式没有计算为一个数据类型,则函数返回None。在JavaScirpt中,void代表none

return语句终止函数并退出函数执行。

def multiplier(num1, num2):
  return num1 * num2

result = multiplier(2,3)
print(result) # 6

是时候用return语句是做一些更有用的事情了。

def sum(num1):
  def child(num2):
    return num1 + num2
  return child

add_10 = sum(10)
print(add_10(20)) # 30  (闭包)
print(add_10(50)) # 60
print(add_10(100)) # 110

我刚刚验证了在Python的闭包概念与JavaScript类似。它能使我们非常有效的创建工厂函数。在上面的代码中,我创建了一个通用的add_10函数,给它传入动态(不同)的参数会产生不同的结果。

在下周学习Python函数式编程的概念时,我们将会进一步探讨。

方法是定义在一个对象中的简单函数,它们“属于”这个对象,需要通过在对象名称后面通过.操作符进行调用。

文档字符串

当我们自定义函数时,使用文档字符串可以让同事或者用户在使用它们时很容易理解函数的用途,这是非常有用的。IDE可以显示函数的信息。如果有一些辅助函数和方法的话可以看到更多的信息。

“代码告诉怎么做;注释告诉你为什么”——— Jeff Atwood

def test_function():
  '''
 函数用来进行打印测试
  '''
  print('test')

test_function()

“阅读代码比编程代码更加频繁”——Guido van Rossum

*args and **kwargs

*argsarguments的简写,**kwargs表示关键字参数。当函数需要接受任意数量的实参或者关键字实参时,可以使用这些参数。

【译者注:

​ 这里作者的描述并不是很准确,可以这样理解:

*agrs——将所有参数以元组(tuple)的形式导入;

**kwargs——将参数以字典的形式导入

def powerful_function(*args):
  print(args)

powerful_function(1,3,2) # (1, 3, 2) --> 返回一个元组

def super_function(**kwargs):
  print(kwargs)

super_function(name='John', age='45') # {'name': 'John', 'age': '45'} --> 返回一个字典

在JavaScript中,ES6里的rest参数用于接受所有的函数参数。

作用域

一句话解释作用域就是**我能用哪些变量?这是解释器在阅读代码以查找变量作用域时问的一类问题。在Python中有函数作用域**,意思是说定义在函数内部的变量不能够被函数外部访问。

num = 1
def confusing_function():
    num = 10
    return num

print(num) # 1 => 全局作用域
print(confusing_function()) # 10 => 局部作用域

以下是Python解释器遵循的作用域规则:

  • 先从局部作用域开始,查看变量是否存在,存在则获取值,如果不存在则继续处理
  • 变量在父函数的局部作用域里有定义吗?如果存在,则继续
  • 变量在全局作用域有定义吗?如果存在,则继续
  • 变量是内置函数吗?如果有则获取,如果没有则结束

阅读更多关于Python作用域的内容

这是一篇关于作用域的最好的文章

这就是我们今天所有的内容了。到现在为止己经涵盖了Python的大部分基础内容。是时候进阶更高级的主题了,但是在这之前,我将探索并且安装开发环境,以及不同开发工具和程序,以完成第一周的路线图。

我希望尽量通俗易懂的记录我学习Python过程。如果你感到困惑或如果你有任何其他的建议和想法,请在评论中告诉我。

原文链接

30 Days of Python 👨‍💻 - Day 6 - Loops II & Functions