标签 python 下的文章

学习怎么去使用 Python 的 web 框架中的对象关系映射与你的数据库交互,就像你使用 SQL 一样。

 title=

你可能听说过 Django,它是一个被称为“完美主义者的最后期限” 的 Python web 框架。它是一匹 可爱的小矮马

Django 的一个强大的功能是它的 对象关系映射 Object-Relational Mapper (ORM),它允许你就像使用 SQL 一样去和你的数据库交互。事实上,Django 的 ORM 就是创建 SQL 去查询和操作数据库的一个 Python 式方式,并且获得 Python 风格的结果。 我说的一种方式,但实际上,它是一种非常聪明的工程方法,它利用了 Python 中一些很复杂的部分,而使得开发者更加轻松。

在我们开始去了解 ORM 是怎么工作之前,我们需要一个可以操作的数据库。和任何一个关系型数据库一样,我们需要去定义一堆表和它们的关系(即,它们相互之间联系起来的方式)。让我们使用我们熟悉的东西。比如说,我们需要去建模一个有博客文章和作者的博客。每个作者有一个名字。一位作者可以有很多的博客文章。一篇博客文章可以有很多的作者、标题、内容和发布日期。

在 Django 村里,这个文章和作者的概念可以被称为博客应用。在这个语境中,一个应用是一个自包含一系列描述我们的博客行为和功能的模型和视图的集合。用正确的方式打包,以便于其它的 Django 项目可以使用我们的博客应用。在我们的项目中,博客正是其中的一个应用。比如,我们也可以有一个论坛应用。但是,我们仍然坚持我们的博客应用的原有范围。

这是为这个教程事先准备的 models.py

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    published_date = models.DateTimeField(blank=True, null=True)
    author = models.ManyToManyField(Author, related_name="posts")

    def __str__(self):
        return self.title

现在,看上去似乎有点令人恐惧,因此,我们把它分解来看。我们有两个模型:作者(Author)和文章(Post)。它们都有名字(name)或者标题(title)。文章有个放内容的大的文本字段,以及用于发布时间和日期的 DateTimeField。文章也有一个 ManyToManyField,它同时链接到文章和作者。

大多数的教程都是从头开始的,但是,在实践中并不会发生这种情况。实际上,你会得到一堆已存在的代码,就像上面的 model.py 一样,而你必须去搞清楚它们是做什么的。

因此,现在你的任务是去进入到应用程序中去了解它。做到这一点有几种方法,你可以登入到 Django admin,这是一个 Web 后端,它会列出全部的应用和操作它们的方法。我们先退出它,现在我们感兴趣的东西是 ORM。

我们可以在 Django 项目的主目录中运行 python manage.py shell 去访问 ORM。

/srv/web/django/ $ python manage.py shell

Python 3.6.3 (default, Nov  9 2017, 15:58:30)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

这将带我们进入到交互式控制台。shell 命令 为我们做了很多设置,包括导入我们的设置和配置 Django 环境。虽然我们启动了 shell,但是,在我们导入它之前,我们并不能访问我们的博客模型。

>>> from blog.models import *

它导入了全部的博客模型,因此,我们可以玩我们的博客了。

首先,我们列出所有的作者:

>>> Author.objects.all()

我们将从这个命令取得结果,它是一个 QuerySet,它列出了我们所有的作者对象。它不会充满我们的整个控制台,因为,如果有很多查询结果,Django 将自动截断输出结果。

>>> Author.objects.all()
<QuerySet [<Author: VM (Vicky) Brasseur>, <Author: Rikki Endsley>,
 <Author: Jen Wike Huger>, '...(remaining elements truncated)...']

我们可以使用 get 代替 all 去检索单个作者。但是,我们需要一些更多的信息才能 get 一个单个记录。在关系型数据库中,表有一个主键,它唯一标识了表中的每个记录,但是,作者名并不唯一。许多人都 重名,因此,它不是唯一约束的好选择。解决这个问题的一个方法是使用一个序列(1、2、3 ……)或者一个通用唯一标识符(UUID)作为主键。但是,因为它对人类并不好用,我们可以通过使用 name 来操作我们的作者对象。

>>> Author.objects.get(name="VM (Vicky) Brasseur")
<Author: VM (Vicky) Brasseur>

到现在为止,我们已经有了一个我们可以交互的对象,而不是一个 QuerySet 列表。我们现在可以与这个 Python 对象进行交互了,使用任意一个表列做为属性去查看对象。

>>> vmb = Author.objects.get(name="VM (Vicky) Brasseur")
>>> vmb.name
u'VM (Vicky) Brasseur'

然后,很酷的事件发生了。通常在关系型数据库中,如果我们希望去展示其它表的信息,我们需要去写一个 LEFT JOIN,或者其它的表耦合函数,并确保它们之间有匹配的外键。而 Django 可以为我们做到这些。

在我们的模型中,由于作者写了很多的文章,因此,我们的作者对象可以检索他自己的文章。

>>> vmb.posts.all()
QuerySet[<Post: "7 tips for nailing your job interview">,
 <Post: "5 tips for getting the biggest bang for your cover letter buck">,
 <Post: "Quit making these 10 common resume mistakes">,
 '...(remaining elements truncated)...']

我们可以使用正常的 Python 式的列表操作方式来操作 QuerySets

>>> for post in vmb.posts.all():
...   print(post.title)
...
7 tips for nailing your job interview
5 tips for getting the biggest bang for your cover letter buck
Quit making these 10 common resume mistakes

要实现更复杂的查询,我们可以使用过滤得到我们想要的内容。这有点复杂。在 SQL 中,你可以有一些选项,比如,likecontains 和其它的过滤对象。在 ORM 中这些事情也可以做到。但是,是通过 特别的 方式实现的:是通过使用一个隐式(而不是显式)定义的函数实现的。

如果在我的 Python 脚本中调用了一个函数 do_thing(),我会期望在某个地方有一个匹配的 def do_thing。这是一个显式的函数定义。然而,在 ORM 中,你可以调用一个 不显式定义的 函数。之前,我们使用 name 去匹配一个名字。但是,如果我们想做一个子串搜索,我们可以使用 name__contains

>>> Author.objects.filter(name__contains="Vic")
QuerySet[<Author: VM (Vicky) Brasseur>, <Author: Victor Hugo">]

现在,关于双下划线(__)我有一个小小的提示。这些是 Python 特有的。在 Python 的世界里,你可以看到如 __main__ 或者 __repr__。这些有时被称为 dunder methods,是 “ 双下划线 double underscore ” 的缩写。仅有几个非字母数字的字符可以被用于 Python 中的对象名字;下划线是其中的一个。这些在 ORM 中被用于显式分隔 过滤关键字 filter key name 的各个部分。在底层,字符串用这些下划线分割开,然后这些标记分开处理。name__contains 被替换成 attribute: name, filter: contains。在其它编程语言中,你可以使用箭头代替,比如,在 PHP 中是 name->contains。不要被双下划线吓着你,正好相反,它们是 Python 的好帮手(并且如果你斜着看,你就会发现它看起来像一条小蛇,想去帮你写代码的小蟒蛇)。

ORM 是非常强大并且是 Python 特有的。不过,还记得我在上面提到过的 Django 的管理网站吗?

 title=

Django 的其中一个非常精彩的用户可访问特性是它的管理界面,如果你定义你的模型,你将看到一个非常好用的基于 web 的编辑门户,而且它是免费的。

ORM,有多强大?

 title=

好吧!给你一些代码去创建最初的模型,Django 就变成了一个基于 web 的门户,它是非常强大的,它可以使用我们前面用过的同样的原生函数。默认情况下,这个管理门户只有基本的东西,但这只是在你的模型中添加一些定义去改变外观的问题。例如,在早期的这些 __str__ 方法中,我们使用这些去定义作者对象应该有什么?(在这种情况中,比如,作者的名字),做了一些工作后,你可以创建一个界面,让它看起来像一个内容管理系统,以允许你的用户去编辑他们的内容。(例如,为一个标记为 “已发布” 的文章,增加一些输入框和过滤)。

如果你想去了解更多内容,Django 美女的教程 中关于 the ORM 的节有详细的介绍。在 Django project website 上也有丰富的文档。

(题图 Christian Holmér,Opensource.com 修改. CC BY-SA 4.0


作者简介:

Katie McLaughlin - Katie 在过去的这几年有许多不同的头衔,她以前是使用多种语言的一位软件开发人员,多种操作系统的系统管理员,和多个不同话题的演讲者。当她不改变 “世界” 的时候,她也去享受烹饪、挂毯艺术,和去研究各种应用程序栈怎么去处理 emoji。


via: https://opensource.com/article/17/11/django-orm

作者:Katie McLaughlin 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

不论是经验丰富的老程序员,还是没有经验的新手,Python 都是一个非常好的编程语言。

Python 是一个非常流行的编程语言,它可以用于创建桌面应用程序、3D 图形、视频游戏、甚至是网站。它是非常好的首选编程语言,因为它易于学习,不像一些复杂的语言,比如,C、 C++、 或 Java。 即使如此, Python 依然也是强大且健壮的,足以创建高级的应用程序,并且几乎适用于所有使用电脑的行业。不论是经验丰富的老程序员,还是没有经验的新手,Python 都是一个非常好的编程语言。

安装 Python

在学习 Python 之前,你需要先去安装它:

Linux: 如果你使用的是 Linux 系统, Python 是已经包含在里面了。但是,你如果确定要使用 Python 3 。应该去检查一下你安装的 Python 版本,打开一个终端窗口并输入:

python3 -V

如果提示该命令没有找到,你需要从你的包管理器中去安装 Python 3。

MacOS: 如果你使用的是一台 Mac,可以看上面 Linux 的介绍来确认是否安装了 Python 3。MacOS 没有内置的包管理器,因此,如果发现没有安装 Python 3,可以从 python.org/downloads/mac-osx 安装它。即使 macOS 已经安装了 Python 2,你还是应该学习 Python 3。

Windows: 微软 Windows 当前是没有安装 Python 的。从 python.org/downloads/windows 安装它。在安装向导中一定要选择 Add Python to PATH 来将 Python 执行程序放到搜索路径。

在 IDE 中运行

在 Python 中写程序,你需要准备一个文本编辑器,使用一个集成开发环境(IDE)是非常实用的。IDE 在一个文本编辑器中集成了一些方便而有用的 Python 功能。IDLE 3 和 NINJA-IDE 是你可以考虑的两种选择:

IDLE 3

Python 自带的一个基本的 IDE 叫做 IDLE。

 title=

它有关键字高亮功能,可以帮助你检测拼写错误,并且有一个“运行”按钮可以很容易地快速测试代码。

要使用它:

  • 在 Linux 或 macOS 上,启动一个终端窗口并输入 idle3
  • 在 Windows,从开始菜单中启动 Python 3。

    • 如果你在开始菜单中没有看到 Python,在开始菜单中通过输入 cmd 启动 Windows 命令提示符,然后输入 C:\Windows\py.exe
    • 如果它没有运行,试着重新安装 Python。并且确认在安装向导中选择了 “Add Python to PATH”。参考 docs.python.org/3/using/windows.html 中的详细介绍。
    • 如果仍然不能运行,那就使用 Linux 吧!它是免费的,只要将你的 Python 文件保存到一个 U 盘中,你甚至不需要安装它就可以使用。

Ninja-IDE

Ninja-IDE 是一个优秀的 Python IDE。它有关键字高亮功能可以帮助你检测拼写错误、引号和括号补全以避免语法错误,行号(在调试时很有帮助)、缩进标记,以及运行按钮可以很容易地进行快速代码测试。

 title=

要使用它:

  1. 安装 Ninja-IDE。如果你使用的是 Linux,使用包管理器安装是非常简单的;否则, 从 NINJA-IDE 的网站上 下载 合适的安装版本。
  2. 启动 Ninja-IDE。
  3. 转到 Edit 菜单,并选择 Preferences 设置。
  4. 在 Preferences 窗口中,点击 Execution 选项卡。
  5. 在 Execution 选项卡上,更改 pythonpython3

 title=

Ninja-IDE 中的 Python3

告诉 Python 想做什么

关键字可以告诉 Python 你想要做什么。不论是在 IDLE 还是在 Ninja 中,转到 File 菜单并创建一个新文件。对于 Ninja 用户:不要创建一个新项目,仅创建一个新文件。

在你的新的空文件中,在 IDLE 或 Ninja 中输入以下内容:

    print("Hello world.")
  • 如果你使用的是 IDLE,转到 Run 菜单并选择 Run module 选项。
  • 如果你使用的是 Ninja,在左侧按钮条中点击 Run File 按钮。

 title=

在 Ninja 中运行文件

关键字 print 告诉 Python 去打印输出在圆括号中引用的文本内容。

虽然,这并不是特别刺激。在其内部, Python 只能访问基本的关键字,像 printhelp,最基本的数学函数,等等。

可以使用 import 关键字加载更多的关键字。在 IDLE 或 Ninja 中开始一个新文件,命名为 pen.py

警告:不要命名你的文件名为 turtle.py,因为名为 turtle.py 的文件是包含在你正在控制的 turtle (海龟)程序中的。命名你的文件名为 turtle.py ,将会把 Python 搞糊涂,因为它会认为你将导入你自己的文件。

在你的文件中输入下列的代码,然后运行它:

    import turtle

Turtle 是一个非常有趣的模块,试着这样做:

    turtle.begin_fill()
    turtle.forward(100)
    turtle.left(90)
    turtle.forward(100)
    turtle.left(90)
    turtle.forward(100)
    turtle.left(90)
    turtle.forward(100)
    turtle.end_fill()

看一看你现在用 turtle 模块画出了一个什么形状。

要擦除你的海龟画图区,使用 turtle.clear() 关键字。想想看,使用 turtle.color("blue") 关键字会出现什么情况?

尝试更复杂的代码:

    import turtle as t
    import time

    t.color("blue")
    t.begin_fill()

    counter=0

    while counter < 4:
        t.forward(100)
        t.left(90)
        counter = counter+1

    t.end_fill()
    time.sleep(5)

运行完你的脚本后,是时候探索更有趣的模块了。

通过创建一个游戏来学习 Python

想学习更多的 Python 关键字,和用图形编程的高级特性,让我们来关注于一个游戏逻辑。在这个教程中,我们还将学习一些关于计算机程序是如何构建基于文本的游戏的相关知识,在游戏里面计算机和玩家掷一个虚拟骰子,其中掷的最高的是赢家。

规划你的游戏

在写代码之前,最重要的事情是考虑怎么去写。在他们写代码 之前,许多程序员是先 写简单的文档,这样,他们就有一个编程的目标。如果你想给这个程序写个文档的话,这个游戏看起来应该是这样的:

  1. 启动掷骰子游戏并按下 Return 或 Enter 去掷骰子
  2. 结果打印在你的屏幕上
  3. 提示你再次掷骰子或者退出

这是一个简单的游戏,但是,文档会告诉你需要做的事很多。例如,它告诉你写这个游戏需要下列的组件:

  • 玩家:你需要一个人去玩这个游戏。
  • AI:计算机也必须去掷,否则,就没有什么输或赢了
  • 随机数:一个常见的六面骰子表示从 1-6 之间的一个随机数
  • 运算:一个简单的数学运算去比较一个数字与另一个数字的大小
  • 一个赢或者输的信息
  • 一个再次玩或退出的提示

制作掷骰子游戏的 alpha 版

很少有程序,一开始就包含其所有的功能,因此,它们的初始版本仅实现最基本的功能。首先是几个定义:

变量是一个经常要改变的值,它在 Python 中使用的非常多。每当你需要你的程序去“记住”一些事情的时候,你就要使用一个变量。事实上,运行于代码中的信息都保存在变量中。例如,在数学方程式 x + 5 = 20 中,变量是 x ,因为字母 x 是一个变量占位符。

整数是一个数字, 它可以是正数也可以是负数。例如,1-1 都是整数,因此,1421,甚至 10947 都是。

在 Python 中变量创建和使用是非常容易的。这个掷骰子游戏的初始版使用了两个变量: playerai

在命名为 dice_alpha.py 的新文件中输入下列代码:

    import random

    player = random.randint(1,6)
    ai = random.randint(1,6)

    if player > ai :
        print("You win")  # notice indentation
    else:
        print("You lose")

启动你的游戏,确保它能工作。

这个游戏的基本版本已经工作的非常好了。它实现了游戏的基本目标,但是,它看起来不像是一个游戏。玩家不知道他们摇了什么,电脑也不知道摇了什么,并且,即使玩家还想玩但是游戏已经结束了。

这是软件的初始版本(通常称为 alpha 版)。现在你已经确信实现了游戏的主要部分(掷一个骰子),是时候该加入到程序中了。

改善这个游戏

在你的游戏的第二个版本中(称为 beta 版),将做一些改进,让它看起来像一个游戏。

1、 描述结果

不要只告诉玩家他们是赢是输,他们更感兴趣的是他们掷的结果。在你的代码中尝试做如下的改变:

    player = random.randint(1,6)
    print("You rolled " + player)

    ai = random.randint(1,6)
    print("The computer rolled " + ai)

现在,如果你运行这个游戏,它将崩溃,因为 Python 认为你在尝试做数学运算。它认为你试图在 player 变量上加字母 You rolled ,而保存在其中的是数字。

你必须告诉 Python 处理在 playerai 变量中的数字,就像它们是一个句子中的单词(一个字符串)而不是一个数学方程式中的一个数字(一个整数)。

在你的代码中做如下的改变:

    player = random.randint(1,6)
    print("You rolled " + str(player) )

    ai = random.randint(1,6)
    print("The computer rolled " + str(ai) )

现在运行你的游戏将看到该结果。

2、 让它慢下来

计算机运行的非常快。人有时可以很快,但是在游戏中,产生悬念往往更好。你可以使用 Python 的 time 函数,在这个紧张时刻让你的游戏慢下来。

    import random
    import time

    player = random.randint(1,6)
    print("You rolled " + str(player) )

    ai = random.randint(1,6)
    print("The computer rolls...." )
    time.sleep(2)
    print("The computer has rolled a " + str(player) )

    if player > ai :
        print("You win")  # notice indentation
    else:
        print("You lose")

启动你的游戏去测试变化。

3、 检测关系

如果你多玩几次你的游戏,你就会发现,即使你的游戏看起来运行很正确,它实际上是有一个 bug 在里面:当玩家和电脑摇出相同的数字的时候,它就不知道该怎么办了。

去检查一个值是否与另一个值相等,Python 使用 ==。那是个“双”等号标记,不是一个。如果你仅使用一个,Python 认为你尝试去创建一个新变量,但是,实际上你是去尝试做数学运算。

当你想有比两个选项(即,赢或输)更多的选择时,你可以使用 Python 的 elif 关键字,它的意思是“否则,如果”。这允许你的代码去检查,是否在“许多”结果中有一个是 true, 而不是只检查“一个”是 true

像这样修改你的代码:

    if player > ai :
        print("You win")  # notice indentation
    elif player == ai:
        print("Tie game.")
    else:
        print("You lose")

多运行你的游戏几次,去看一下你能否和电脑摇出一个平局。

编写最终版

你的掷骰子游戏的 beta 版的功能和感觉比起 alpha 版更像游戏了,对于最终版,让我们来创建你的第一个 Python 函数

函数是可以作为一个独立的单元来调用的一组代码的集合。函数是非常重要的,因为,大多数应用程序里面都有许多代码,但不是所有的代码都只运行一次。函数可以启用应用程序并控制什么时候可以发生什么事情。

将你的代码变成这样:

    import random
    import time

    def dice():
        player = random.randint(1,6)
        print("You rolled " + str(player) )

        ai = random.randint(1,6)
        print("The computer rolls...." )
        time.sleep(2)
        print("The computer has rolled a " + str(player) )

        if player > ai :
            print("You win")  # notice indentation
        else:
            print("You lose")

        print("Quit? Y/N")
        cont = input()

        if cont == "Y" or cont == "y":
            exit()
        elif cont == "N" or cont == "n":
            pass
        else:
            print("I did not understand that. Playing again.")

游戏的这个版本,在他们玩游戏之后会询问玩家是否退出。如果他们用一个 Yy 去响应, Python 就会调用它的 exit 函数去退出游戏。

更重要的是,你将创建一个称为 dice 的你自己的函数。这个 dice 函数并不会立即运行,事实上,如果在这个阶段你尝试去运行你的游戏,它不会崩溃,但它也不会正式运行。要让 dice 函数真正运行起来做一些事情,你必须在你的代码中去调用它

在你的现有代码下面增加这个循环,前两行就是上文中的前两行,不需要再次输入,并且要注意哪些需要缩进哪些不需要。要注意缩进格式

        else:
            print("I did not understand that. Playing again.")

    # main loop
    while True:
        print("Press return to roll your die.")
        roll = input()
        dice()

while True 代码块首先运行。因为 True 被定义为总是真,这个代码块将一直运行,直到 Python 告诉它退出为止。

while True 代码块是一个循环。它首先提示用户去启动这个游戏,然后它调用你的 dice 函数。这就是游戏的开始。当 dice 函数运行结束,根据玩家的回答,你的循环再次运行或退出它。

使用循环来运行程序是编写应用程序最常用的方法。循环确保应用程序保持长时间的可用,以便计算机用户使用应用程序中的函数。

下一步

现在,你已经知道了 Python 编程的基础知识。这个系列的下一篇文章将描述怎么使用 PyGame 去编写一个视频游戏,一个比 turtle 模块有更多功能的模块,但它也更复杂一些。


作者简介:

Seth Kenlon - 一个独立的多媒体大师,自由文化的倡导者,和 UNIX 极客。他同时从事电影和计算机行业。他是基于 slackwarers 的多媒体制作项目的维护者之一, http://slackermedia.info


via: https://opensource.com/article/17/10/python-101

作者:Seth Kenlon 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

运用这些很棒的 Python 爬虫工具来获取你需要的数据。

 title=

在一个理想的世界里,你需要的所有数据都将以公开而文档完备的格式清晰地展现,你可以轻松地下载并在任何你需要的地方使用。

然而,在真实世界里,数据是凌乱的,极少被打包成你需要的样子,要么经常是过期的。

你所需要的信息经常是潜藏在一个网站里。相比一些清晰地、有调理地呈现数据的网站,更多的网站则不是这样的。 爬取数据 crawling 挖掘数据 scraping 、加工数据、整理数据这些是获取整个网站结构来绘制网站拓扑来收集数据所必须的活动,这些可以是以网站的格式储存的或者是储存在一个专有数据库中。

也许在不久的将来,你需要通过爬取和挖掘来获得一些你需要的数据,当然你几乎肯定需要进行一点点的编程来正确的获取。你要怎么做取决于你自己,但是我发现 Python 社区是一个很好的提供者,它提供了工具、框架以及文档来帮助你从网站上获取数据。

在我们进行之前,这里有一个小小的请求:在你做事情之前请思考,以及请耐心。抓取这件事情并不简单。不要把网站爬下来只是复制一遍,并其它人的工作当成是你自己的东西(当然,没有许可)。要注意版权和许可,以及你所爬行的内容应用哪一个标准。尊重 robots.txt 文件。不要频繁的针对一个网站,这将导致真实的访问者会遇到访问困难的问题。

在知晓这些警告之后,这里有一些很棒的 Python 网站爬虫工具,你可以用来获得你需要的数据。

Pyspider

让我们先从 pyspider 开始介绍。这是一个带有 web 界面的网络爬虫,让与使之容易跟踪多个爬虫。其具有扩展性,支持多个后端数据库和消息队列。它还具有一些方便的特性,从优先级到再次访问抓取失败的页面,此外还有通过时间顺序来爬取和其他的一些特性。Pyspider 同时支持 Python 2 和 Python 3。为了实现一个更快的爬取,你可以在分布式的环境下一次使用多个爬虫进行爬取。

Pyspyder 的基本用法都有良好的 文档说明 ,包括简单的代码片段。你能通过查看一个 在线的样例 来体验用户界面。它在 Apache 2 许可证下开源,Pyspyder 仍然在 GitHub 上积极地开发。

MechanicalSoup

MechanicalSoup 是一个基于极其流行而异常多能的 HTML 解析库 Beautiful Soup 建立的爬虫库。如果你的爬虫需要相当的简单,但是又要求检查一些选择框或者输入一些文字,而你又不想为这个任务单独写一个爬虫,那么这会是一个值得考虑的选择。

MechanicalSoup 在 MIT 许可证下开源。查看 GitHub 上该项目的 example.py 样例文件来获得更多的用法。不幸的是,到目前为止,这个项目还没有一个很好的文档。

Scrapy

Scrapy 是一个有着活跃社区支持的抓取框架,在那里你可以建造自己的抓取工具。除了爬取和解析工具,它还能将它收集的数据以 JSON 或者 CSV 之类的格式轻松输出,并存储在一个你选择的后端数据库。它还有许多内置的任务扩展,例如 cookie 处理、代理欺骗、限制爬取深度等等,同时还可以建立你自己附加的 API。

要了解 Scrapy,你可以查看网上的文档或者是访问它诸多的社区资源,包括一个 IRC 频道、Reddit 子版块以及关注他们的 StackOverflow 标签。Scrapy 的代码在 3 句版 BSD 许可证下开源,你可以在 GitHub 上找到它们。

如果你完全不熟悉编程,Portia 提供了一个易用的可视化的界面。scrapinghub.com 则提供一个托管的版本。

其它

  • Cola 自称它是个“高级的分布式爬取框架”,如果你在寻找一个 Python 2 的方案,这也许会符合你的需要,但是注意它已经有超过两年没有更新了。
  • Demiurge 是另一个可以考虑的潜在候选者,它同时支持 Python 2和 Python 3,虽然这个项目的发展较为缓慢。
  • 如果你要解析一些 RSS 和 Atom 数据,Feedparser 或许是一个有用的项目。
  • Lassie 让从网站检索像说明、标题、关键词或者是图片一类的基本内容变得简单。
  • RoboBrowser 是另一个简单的库,它基于 Python 2 或者 Python 3,它具有按钮点击和表格填充的基本功能。虽然它有一段时间没有更新了,但是它仍然是一个不错的选择。

这远不是一个完整的列表,当然,如果你是一个编程专家,你可以选择采取你自己的方法而不是使用这些框架中的一个。或者你发现一个用其他语言编写的替代品。例如 Python 编程者可能更喜欢 Python 附带的 Selenium,它可以在不使用实际浏览器的情况下进行爬取。如果你有喜欢的爬取和挖掘工具,请在下面评论让我们知道。

(题图:You as a Machine. Modified by Rikki Endsley. CC BY-SA 2.0


via: https://opensource.com/resources/python/web-scraper-crawler

作者:Jason Baker 译者:ZH1122 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

你可能在各种应用中听说过 机器学习 machine learning (ML),比如垃圾邮件过滤、光学字符识别(OCR)和计算机视觉。

开启机器学习之旅是一个涉及多方面的漫长旅途。对于新手,有很多的书籍,有学术论文,有指导练习,有独立项目。在这些众多的选择里面,很容易迷失你最初想学习的目标。

所以在今天的文章中,我会列出 7 个步骤(和 50 多个资源)帮助你开启这个令人兴奋的计算机科学领域的大门,并逐渐成为一个机器学习高手。

请注意,这个资源列表并不详尽,只是为了让你入门。 除此之外,还有更多的资源。

1、 学习必要的背景知识

你可能还记得 DataCamp 网站上的学习数据科学这篇文章里面的信息图:数学和统计学是开始机器学习(ML)的关键。 基础可能看起来很容易,因为它只有三个主题。 但不要忘记这些实际上是三个广泛的话题。

在这里需要记住两件非常重要的事情:

  • 首先,你一定会需要一些进一步的指导,以了解开始机器学习需要覆盖哪些知识点。
  • 其次,这些是你进一步学习的基础。 不要害怕花时间,有了这些知识你才能构建一切。

第一点很简单:学习线性代数和统计学是个好主意。这两门知识是必须要理解的。但是在你学习的同时,也应该尝试学习诸如最优化和高等微积分等主题。当你越来越深入 ML 的时候,它们就能派上用场。

如果是从零开始的,这里有一些入门指南可供参考:

统计学是学习 ML 的关键之一

如果你更多喜欢阅读书籍,请参考以下内容:

然而,在大多数情况下,你已经对统计学和数学有了一个初步的了解。很有可能你已经浏览过上面列举的的那些资源。

在这种情况下,诚实地回顾和评价你的知识是一个好主意,是否有一些领域是需要复习的,或者现在掌握的比较好的?

如果你一切都准备好了,那么现在是时候使用 R 或者 Python 应用这些知识了。作为一个通用的指导方针,选择一门语言开始是个好主意。另外,你仍然可以将另一门语言加入到你的技能池里。

为什么这些编程知识是必需的?

嗯,你会看到上面列出的课程(或你在学校或大学学习的课程)将为你提供关于数学和统计学主题的更理论性的介绍(而不是应用性的)。 然而,ML 非常便于应用,你需要能够应用你所学到的所有主题。 所以最好再次复习一遍之前的材料,但是这次需要付诸应用。

如果你想掌握 R 和 Python 的基础,可以看以下课程:

当你打牢基础知识后,请查看 DataCamp 上的博客 Python 统计学:40+ 数据科学资源。 这篇文章提供了统计学方面的 40 多个资源,这些资源都是你开始数据科学(以及 ML)需要学习的。

还要确保你查看了关于向量和数组的 这篇 SciPy 教程文章,以及使用 Python 进行科学计算的研讨会

要使用 Python 和微积分进行实践,你可以了解下 SymPy 软件包

2、 不要害怕在 ML 的“理论”上浪费时间

很多人并不会花很多精力去浏览理论材料,因为理论是枯燥的、无聊的。但从长远来看,在理论知识上投入时间是至关重要的、非常值得的。 你将会更好地了解机器学习的新进展,也能和背景知识结合起来。 这将有助于你保持学习积极性。

此外,理论并不会多无聊。 正如你在介绍中所看到的,你可以借助非常多的资料深入学习。

书籍是吸收理论知识的最佳途径之一。 它们可以让你停下来想一会儿。 当然,看书是一件非常平静的事情,可能不符合你的学习风格。 不过,请尝试阅读下列书籍,看看它是否适合你:

  • 机器学习教程 Machine Learning textbook , Tom Mitchell 著,书可能比较旧,但是却很经典。这本书很好的解释介绍了机器学习中最重要的课题,步骤详尽,逐层深入。
  • 机器学习: 使数据有意义的算法艺术和科学 Machine Learning: The Art and Science of Algorithms that Make Sense of Data (你可以在这里看到这本书的幻灯片版本):这本书对初学者来说非常棒。 里面讨论了许多实践中的应用程序,其中有一些是在 Tom Mitchell 的书中缺少的。
  • 机器学习之向往 Machine Learning Yearning :这本书由 吴恩达 Andrew Ng 编写的,仍未完本,但对于那些正在学习 ML 的学生来说,这一定是很好的参考资料。
  • 算法与数据结构 Algorithms and Data Structures 由 Jurg Nievergelt 和 Klaus Hinrichs 著。
  • 也可以参阅 Matthew North 的 面向大众的数据挖掘 Data Mining for the Masses 。 你会发现这本书引导你完成一些最困难的主题。
  • 机器学习介绍 Introduction to Machine Learning 由 Alex Smola 和 S.V.N. Vishwanathan 著。

花些时间看书并研究其中涵盖的资料

视频和慕课对于喜欢边听边看来学习的人来说非常棒。 慕课和视频非常的多,多到可能你都很难找到适合你的。 下面列出了最知名的几个:

在这一点上,重要的是要将各种独立的技术融会贯通,形成整体的结构图。 首先了解关键的概念: 监督学习 supervised learning 无监督学习 unsupervised learning 的区别、分类和回归等。 手动(书面)练习可以派上用场,能帮你了解算法是如何工作的以及如何应用这些算法。 在大学课程里你经常会找到一些书面练习,可以看看波特兰州立大学的 ML 课程

3、 开始动手

通过看书和看视频了解理论和算法都非常好,但是需要超越这一阶段,就要开始做一些练习。你要学着去实现这些算法,应用学到的理论。

首先,有很多介绍 Python 和 R 方面的机器学习的基础知识。当然最好的方法就是使用交互式教程:

还请查看以下静态的(非互动的)教程,这些需要你在 IDE 中操作:

除了教程之外,还有一些课程。参加课程可以帮助你系统性地应用学到的概念。 经验丰富的导师很有帮助。 以下是 Python 和机器学习的一些互动课程:

  • 用 scikit-learn 做监督学习: 学习如何构建预测模型,调整参数,并预测在未知数据上执行的效果。你将使用 Scikit-Learn 操作真实世界的数据集。
  • 用 Python 做无监督学习: 展示给你如何从未标记的数据集进行聚类、转换、可视化和提取关键信息。 在课程结束时,还会构建一个推荐系统。
  • Python 深度学习: 你将获得如何使用 Keras 2.0 进行深度学习的实践知识,Keras 2.0 是前沿的 Python 深度学习库 Keras 的最新版本。
  • 在 Python 中应用机器学习: 将学习者引入到机器学习实践中,更多地关注技术和方法,而不是这些方法背后的统计学知识。

理论学习之后,花点时间来应用你所学到的知识。

对于那些正在学习 R 语言机器学习的人,还有这些互动课程:

  • 机器学习介绍 可以让你宏观了解机器学习学科最常见的技术和应用,还可以更多地了解不同机器学习模型的评估和训练。这门课程剩下的部分重点介绍三个最基本的机器学习任务: 分类、回归和聚类。
  • R 语言无监督学习 ,用 R 语言从 ML 角度提供聚类和降维的基本介绍。 可以让你尽快获得数据的关键信息。
  • 实操机器学习涵盖了构建和应用预测功能的基本组成部分,其重点是实际应用。

最后,还有很多书籍以偏向实践的方式介绍了 ML 主题。 如果你想借助书籍内容和 IDE 来学习,请查看这些书籍:

4、 练习

实践比使用 Python 进行练习和修改材料更重要。 这一步对我来说可能是最难的。 在做了一些练习后看看其他人是如何实现 ML 算法的。 然后,开始你自己的项目,阐述你对 ML 算法和理论的理解。

最直接的方法之一就是将练习的规模做得更大些。 要做一个更大的练习,就需要你做更多的数据清理和功能工程。

熟能生巧。

5、 项目

虽然做一些小的练习也不错,但是在最后,您需要做一个项目,可以在其中展示您对使用到的 ML 算法的理解。

最好的练习是实现你自己的 ML 算法。 您可以在以下页面中阅读更多关于为什么您应该做这样的练习,以及您可以从中学到什么内容:

接下来,您可以查看以下文章和仓库。 可以从中获得一些灵感,并且了解他们是如何实现 ML 算法的。

开始时项目可能会很难,但是可以极大增加你的理解。

6、 不要停止

对 ML 的学习永远不能停止,即使你在这个领域工作了十年,总是有新的东西要学习,许多人都将会证实这一点。

例如,ML 趋势,比如 深度学习 deep learning 现在就很受欢迎。你也可以专注于那些现在不怎么火,但是将来会火的话题上。如果你想了解更多,可以看看这个有趣的问题和答案

当你苦恼于掌握基础知识时,你最先想到的可能不是论文。 但是它们是你紧跟最新研究的一个途径。 论文并不适合刚刚开始学习的人,但是绝对适合高级人员。

其他技术也是需要考虑的。 但是当你刚开始学习时,不要担心这些。 例如,您可以专注于 Python 或 R 语言 (取决于你已经知道哪一个),并把它到你的技能池里。 你可以通过这篇文章来查找一些感兴趣的资源。

如果您还想转向大数据,您可以考虑研究 Spark。 这里有一些有趣的资源:

其他编程语言,比如 Java、JavaScript、C 和 C++ 在 ML 中越来越重要。 从长远来看,您可以考虑将其中一种语言添加到学习列表中。 你可以使用这些博客文章来指导你选择:

学无止境。

7、 利用一切可以利用的资源

机器学习是一个充满难度的话题,有时候可能会让你失去动力。 或者也许你觉得你需要点改变。 在这种情况下,请记住,有很多资源可以让你打消掉这种想法。 查看以下资源:

播客是可以让你继续你的 ML 旅程,紧跟这个领域最新的发展的伟大资源:

当然,还有更多的播客。

文档和软件包源代码是深入了解 ML 算法的实现的两种方法。 查看这些仓库:

  • Scikit-Learn:知名的 Python ML 软件包
  • Keras: Python 深度学习软件包
  • caret: 非常受欢迎的用于分类和回归训练 R 软件包

可视化是深入 ML 理论的最新也是最流行的方式之一。 它们对初学者来说非常棒,但对于更高级的学习者来说也是非常有趣的。 你肯定会被下面这些可视化资源所吸引,它们能让你更加了解 ML 的工作原理:

学习中的一些变化更加能激励你。

现在你可以开始了

现在一切都取决于你自己了。学习机器学习是一个持续的过程,所以开始的越早就会越好。 运用你手边的一切工具开始吧。 祝你好运,并确保让我们知道你的进步。

这篇文章是我基于 Quora 问题(小白该如何开始机器学习)给出的答案。


作者简介:

Karlijn Willems,数据科学记者


via: https://medium.freecodecamp.org/how-machines-learn-a-practical-guide-203aae23cafb

作者:Karlijn Willems 译者:Flowsnow 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

我们最近探讨了那些世界银行定义为高收入的富裕国家是如何倾向于使用与世界上其它地区不同的技术。这其中我们看到的最大的差异在于 Python 编程语言。就高收入国家而言,Python 的增长甚至要比 Stack Overflow Trends 等工具展现的或其他针对全球的软件开发的排名更高。

在本文中,我们将探讨在过去五年中 Python 编程语言的非凡增长,就如在高收入国家的 Stack Overflow 流量所示那样。“增长最快”一词很难准确定义,但是我们认为 Python 确实可以称得上增长最快的主流编程语言。

这篇文章中讨论的所有数字都是针对高收入国家的。它们一般指的是美国、英国、德国、加拿大等国家的趋势,他们加起来占了 Stack Overflow 大约 64% 的流量。许多其他国家,如印度、巴西、俄罗斯和中国,也为全球软件开发生态系统做出了巨大贡献,尽管我们也将看到 Python 在这方面有所增长,但本文对这些经济体的描述较少。

值得强调的是,一种语言的用户数量并不能衡量语言的品质:我们是在描述开发人员使用的语言,但没有规定任何东西。(完全披露:我曾经主要使用 Python 编程,尽管我已经完全切换到 R 了)。

Python 在高收入国家的增长

你可以在 Stack Overflow Trends 中看到,Python 在过去几年中一直在快速增长。但是对于本文,我们将重点关注高收入国家,考虑的是问题的浏览量而不是提出的问题数量(这基本上结果是类似的,但是每个月都有所波动,特别是对于较小的标签分类)。

我们有关于 Stack Overflow 问题的查看数据可以追溯到 2011 年底,在这段时间内,我们可以研究下 Python 相对于其他五种主要编程语言的增长。(请注意,这比 Stack Overflow Trends 的时间范围更短,它可追溯到 2008 年)。这些目前是高收入国家里十大访问最高的 Stack Overflow 标签中的六个。我们没有包括的四个是 CSS、HTML、Android 和 JQuery。

2017 年 6 月,Python 是成为高收入国家里 Stack Overflow 访问量最高的标签的第一个月。这也是美国和英国最受欢迎的标签,以及几乎所有其他高收入国家的前两名(接着就是 Java 或 JavaScript)。这是特别令人印象深刻的,因为在 2012 年,它比其他 5 种语言的访问量小,比当时增长了 2.5 倍。

部分原因是因为 Java 流量的季节性。由于它在本科课程中有很多课程,Java 流量在秋季和春季会上升,夏季则下降。到年底,它会再次赶上 Python 吗?我们可以尝试用一个叫做 “STL” 的模型来预测未来两年的增长, 它将增长与季节性趋势结合起来,来预测将来的变化。

根据这个模型,Python 可能会在秋季保持领先地位或被 Java 取代(大致在模型预测的变化范围之内),但是 Python 显然会在 2018 年成为浏览最多的标签。STL 还表明,与过去两年一样,JavaScript 和 Java 在高收入国家中的流量水平将保持相似水平。

什么标签整体上增长最快?

上面只看了六个最受欢迎的编程语言。在其他重大技术中,哪些是目前在高收入国家中增长最快的技术?

我们以 2017 年至 2016 年流量的比例来定义增长率。在此分析中,我们决定仅考虑编程语言(如 Java 和 Python)和平台(如 iOS、Android、Windows 和 Linux),而不考虑像 AngularTensorFlow 这样的框架(虽然其中许多有显著的增长,可能在未来的文章中分析)。

xkcd - Fastest-Growing

由于上面这个漫画中所描述的“最快增长”定义的激励,我们将增长与平均差异图中的整体平均值进行比较。

Python 以 27% 的年增长率成为了规模大、增长快的标签。下一个类似增长的最大标签是 R。我们看到,大多数其他大型标签的流量在高收入国家中保持稳定,浏览 Android、iOS 和 PHP 则略有下降。我们以前在 Flash 之死这篇文章中审查过一些正在衰减的标签,如 Objective-C、Perl 和 Ruby。我们还注意到,在函数式编程语言中,Scala 是最大的并且不断增长的,而 F# 和 Clojure 较小并且正在衰减,Haskell 则保持稳定。

上面的图表中有一个重要的遗漏:去年,有关 TypeScript 的问题流量增长了惊人的 142%,这使得我们需要去除它以避免压扁比例尺。你还可以看到,其他一些较小的语言的增长速度与 Python 类似或更快(例如 R、Go 和 Rust),而且还有许多标签,如 Swift 和 Scala,这些标签也显示出惊人的增长。它们随着时间的流量相比 Python 如何?

像 R 和 Swift 这样的语言的发展确实令人印象深刻,而 TypeScript 在更短的时间内显示出特别快速的扩张。这些较小的语言中,有许多从很少的流量成为软件生态系统中引人注目的存在。但是如图所示,当标签开始相对较小时,显示出快速增长更容易。

请注意,我们并不是说这些语言与 Python “竞争”。相反,这只是解释了为什么我们要把它们的增长分成一个单独的类别,这些是始于较低流量的标签。Python 是一个不寻常的案例,既是 Stack Overflow 中最受欢迎的标签之一,也是增长最快的其中之一。(顺便说一下,它也在加速!自 2013 年以来,每年的增长速度都会更快)。

世界其他地区

在这篇文章中,我们一直在分析高收入国家的趋势。Python 在世界其他地区,如印度、巴西、俄罗斯和中国等国家的增长情况是否类似?

确实如此。

在高收入国家之外,Python 仍旧是增长最快的主要编程语言。它从较低的水平开始,两年后才开始增长(2014 年而不是 2012 年)。事实上,非高收入国家的 Python 同比增长率高于高收入国家。我们不会在这里研究它,但是 R (其它语言的使用与 GDP 正相关) 在这些国家也在增长。

在这篇文章中,许多关于高收入国家标签 (相对于绝对排名) 的增长和下降的结论,对世界其他地区都是正确的。两个部分增长率之间有一个 0.979 Spearman 相关性。在某些情况下,你可以看到类似于 Python 上发生的 “滞后” 现象,其中一个技术在高收入国家被广泛采用,一年或两年才能在世界其他地区扩大。(这是一个有趣的现象,这可能是未来文章的主题!)

下一次

我们不打算为任何“语言战争”提供弹药。一种语言的用户数量并不意味着它的质量,而且肯定不会让你知道哪种语言更适合某种特定情况。不过,考虑到这点,我们认为值得了解什么语言构成了开发者生态系统,以及生态系统会如何变化。

本文表明 Python 在过去五年中,特别是在高收入国家,显示出惊人的增长。在我们的下一篇文章中,我们将开始研究“为什么”。我们将按国家和行业划分增长情况,并研究有哪些其他技术与 Python 一起使用(例如,估计多少增长是由于 Python 用于 Web 开发而不是数据科学)。

在此期间,如果你使用 Python 工作,并希望你的职业生涯中进入下一阶段,那么在 Stack Overflow Jobs 上有些公司正在招聘 Python 开发


via: https://stackoverflow.blog/2017/09/06/incredible-growth-python/

作者:David Robinson 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这些错误会造成很麻烦的问题,需要数小时才能解决。

当你做错事时,承认错误并不是一件容易的事,但是犯错是任何学习过程中的一部分,无论是学习走路,还是学习一种新的编程语言都是这样,比如学习 Python。

为了让初学 Python 的程序员避免犯同样的错误,以下列出了我学习 Python 时犯的三种错误。这些错误要么是我长期以来经常犯的,要么是造成了需要几个小时解决的麻烦。

年轻的程序员们可要注意了,这些错误是会浪费一下午的!

1、 可变数据类型作为函数定义中的默认参数

这似乎是对的?你写了一个小函数,比如,搜索当前页面上的链接,并可选将其附加到另一个提供的列表中。

def search_for_links(page, add_to=[]):
    new_links = page.search_for_links()
    add_to.extend(new_links)
    return add_to

从表面看,这像是十分正常的 Python 代码,事实上它也是,而且是可以运行的。但是,这里有个问题。如果我们给 add_to 参数提供了一个列表,它将按照我们预期的那样工作。但是,如果我们让它使用默认值,就会出现一些神奇的事情。

试试下面的代码:

def fn(var1, var2=[]):
    var2.append(var1)
    print var2

fn(3)
fn(4)
fn(5)

可能你认为我们将看到:

[3]
[4]
[5]

但实际上,我们看到的却是:

[3]
[3, 4]
[3, 4, 5]

为什么呢?如你所见,每次都使用的是同一个列表,输出为什么会是这样?在 Python 中,当我们编写这样的函数时,这个列表被实例化为函数定义的一部分。当函数运行时,它并不是每次都被实例化。这意味着,这个函数会一直使用完全一样的列表对象,除非我们提供一个新的对象:

fn(3, [4])
[4, 3]

答案正如我们所想的那样。要想得到这种结果,正确的方法是:

def fn(var1, var2=None):
    if not var2:
        var2 = []
    var2.append(var1)

或是在第一个例子中:

def search_for_links(page, add_to=None):
    if not add_to:
        add_to = []
    new_links = page.search_for_links()
    add_to.extend(new_links)
    return add_to

这将在模块加载的时候移走实例化的内容,以便每次运行函数时都会发生列表实例化。请注意,对于不可变数据类型,比如元组字符串整型,是不需要考虑这种情况的。这意味着,像下面这样的代码是非常可行的:

def func(message="my message"):
    print message

2、 可变数据类型作为类变量

这和上面提到的最后一个错误很相像。思考以下代码:

class URLCatcher(object):
    urls = []

    def add_url(self, url):
        self.urls.append(url)

这段代码看起来非常正常。我们有一个储存 URL 的对象。当我们调用 add\_url 方法时,它会添加一个给定的 URL 到存储中。看起来非常正确吧?让我们看看实际是怎样的:

a = URLCatcher()
a.add_url('http://www.google.com')
b = URLCatcher()
b.add_url('http://www.bbc.co.hk')

b.urls:

['http://www.google.com', 'http://www.bbc.co.uk']

a.urls:

['http://www.google.com', 'http://www.bbc.co.uk']

等等,怎么回事?!我们想的不是这样啊。我们实例化了两个单独的对象 ab。把一个 URL 给了 a,另一个给了 b。这两个对象怎么会都有这两个 URL 呢?

这和第一个错例是同样的问题。创建类定义时,URL 列表将被实例化。该类所有的实例使用相同的列表。在有些时候这种情况是有用的,但大多数时候你并不想这样做。你希望每个对象有一个单独的储存。为此,我们修改代码为:

class URLCatcher(object):
    def __init__(self):
        self.urls = []

    def add_url(self, url):
        self.urls.append(url)

现在,当创建对象时,URL 列表被实例化。当我们实例化两个单独的对象时,它们将分别使用两个单独的列表。

3、 可变的分配错误

这个问题困扰了我一段时间。让我们做出一些改变,并使用另一种可变数据类型 - 字典

a = {'1': "one", '2': 'two'}

现在,假设我们想把这个字典用在别的地方,且保持它的初始数据完整。

b = a

b['3'] = 'three'

简单吧?

现在,让我们看看原来那个我们不想改变的字典 a

{'1': "one", '2': 'two', '3': 'three'}

哇等一下,我们再看看 b

{'1': "one", '2': 'two', '3': 'three'}

等等,什么?有点乱……让我们回想一下,看看其它不可变类型在这种情况下会发生什么,例如一个元组

c = (2, 3)
d = c
d = (4, 5)

现在 c(2, 3),而 d(4, 5)

这个函数结果如我们所料。那么,在之前的例子中到底发生了什么?当使用可变类型时,其行为有点像 C 语言的一个指针。在上面的代码中,我们令 b = a,我们真正表达的意思是:b 成为 a 的一个引用。它们都指向 Python 内存中的同一个对象。听起来有些熟悉?那是因为这个问题与先前的相似。其实,这篇文章应该被称为「可变引发的麻烦」。

列表也会发生同样的事吗?是的。那么我们如何解决呢?这必须非常小心。如果我们真的需要复制一个列表进行处理,我们可以这样做:

b = a[:]

这将遍历并复制列表中的每个对象的引用,并且把它放在一个新的列表中。但是要注意:如果列表中的每个对象都是可变的,我们将再次获得它们的引用,而不是完整的副本。

假设在一张纸上列清单。在原来的例子中相当于,A 某和 B 某正在看着同一张纸。如果有个人修改了这个清单,两个人都将看到相同的变化。当我们复制引用时,每个人现在有了他们自己的清单。但是,我们假设这个清单包括寻找食物的地方。如果“冰箱”是列表中的第一个,即使它被复制,两个列表中的条目也都指向同一个冰箱。所以,如果冰箱被 A 修改,吃掉了里面的大蛋糕,B 也将看到这个蛋糕的消失。这里没有简单的方法解决它。只要你记住它,并编写代码的时候,使用不会造成这个问题的方式。

字典以相同的方式工作,并且你可以通过以下方式创建一个昂贵副本:

b = a.copy()

再次说明,这只会创建一个新的字典,指向原来存在的相同的条目。因此,如果我们有两个相同的列表,并且我们修改字典 a 的一个键指向的可变对象,那么在字典 b 中也将看到这些变化。

可变数据类型的麻烦也是它们强大的地方。以上都不是实际中的问题;它们是一些要注意防止出现的问题。在第三个项目中使用昂贵复制操作作为解决方案在 99% 的时候是没有必要的。你的程序或许应该被改改,所以在第一个例子中,这些副本甚至是不需要的。

编程快乐!在评论中可以随时提问。


作者简介:

Pete Savage - Peter 是一位充满激情的开源爱好者,在过去十年里一直在推广和使用开源产品。他从 Ubuntu 社区开始,在许多不同的领域自愿参与音频制作领域的研究工作。在职业经历方面,他起初作为公司的系统管理员,大部分时间在管理和建立数据中心,之后在 Red Hat 担任 CloudForms 产品的主要测试工程师。


via: https://opensource.com/article/17/6/3-things-i-did-wrong-learning-python

作者:Pete Savage 译者:polebug 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出