整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

学习用 Python 编程时要避免的 3 个错误

学习用 Python 编程时要避免的 3 个错误

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

本文导航
  • -1、 可变数据类型作为函数定义中的默认参数 …… 07%

  • -2、 可变数据类型作为类变量 …… 35%

  • -3、 可变的分配错误 …… 53%

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

作者: Pete Savage

译者: polebug

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

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

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

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']

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

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

class URLCatcher(object):

def __init__(self):

self.urls=[]

def add_url(self, url):

self.urls.append(url)

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

3、 可变的分配错误

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

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[5] 译者:polebug 校对:wxy

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

  • [1]: 元组 - https://docs.python.org/2/library/functions.html?highlight=tuple#tuple

  • [2]: 字符串 - https://docs.python.org/2/library/string.html

  • [3]: 整型 - https://docs.python.org/2/library/functions.html#int

  • [4]: 字典 - https://docs.python.org/2/library/stdtypes.html?highlight=dict#dict

  • [5]: Pete Savage - https://opensource.com/users/psav

DEA 全称 IntelliJ IDEA,是java编程语言开发的集成环境。IntelliJ在业界被公认为最好的java开发工具,尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能可以说是超常的。IDEA是JetBrains公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。它的旗舰版本还支持HTML,CSS,PHP,MySQL,Python等。免费版只支持Java,Kotlin等少数语言。

俗话说:"工欲善其事必先利其器",今天准备和大家一起分享一下实际工作中能提升幸福感和工作效率的IDEA插件。

废话不多说,let's go !!!

1Alibaba Java Coding Guidelines

【阿里巴巴代码规范检查插件】

在你需要检查的代码上面,点击右键,选择编码规约扫描

将会出现如下所示的检查结果,并会给出编码规范和提示:

2GsonFormat

【jsonToBean】

在平时的开发中,将json转为Bean

3A8Translation

【翻译的插件】

选中你要翻译的汉语或英文,点击鼠标右键,选择Translate, (快捷键是Alt+T)就会实现翻译,不用再去切换屏幕使用翻译软件翻译了。

4Maven Helper

【分析依赖冲突的插件】

此插件可用来方便显示maven的依赖树,和显示冲突,在我们梳理依赖时帮助很大。

5Free Mybatis plugin

【增强idea对mybatis支持的插件】

生成mapper xml文件 快速从代码跳转到mapper及从mapper返回代码 mybatis自动补全及语法错误提示 集成mybatis generator gui界面 这个插件超级实用,可以从mapper接口跳转到mybatis的xml文件中,还能找到对应地方

6Grep Console

【日志高亮显示插件】

可以Ctrl + Alt +S Other Settings进行配色(颜色参考请搜索:电脑最护眼的色彩、显示屏亮度亦如此)

7Lombok

当我们创建一个实体时,通常对每个字段去生成GET/SET方法,但是万一后面需要增加或者减少字段时,又要重新的去生成GET/SET方法,非常麻烦。可以通过该插件,无需再写那么多冗余的get/set代码。

注意:需要在pom引入依赖

<!--lombok用来简化实体类:需要安装lombok插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

8Nyan progress bar

基于Idea使用的漂亮进度条。把你的加载进度条全都变成彩虹和猫咪

9FindBugs-IDEA

【Bug检查插件】

在文件上或文件里面点击鼠标右键,选择FingBugs

简单的bug能给你快速找回来,什么NPE啥的,小儿科!推荐!!(嗓门大就说一遍)

10Key Promoter X

你还在为记不住快捷键烦恼吗,Key Promoter X可以帮助你快速记住常用的快捷键。当你在idea中用鼠标点击菜单,它可以显示对应的快捷键以及点击次数。使用一段时间后有助于过渡到更快、无鼠标的开发。

11JavaDoc

在项目中经常要求写代码注释,否则不能通过代码门禁,JavaDoc工具可以一键生成注释。

插件安装成功后在菜单栏 code -> JavaDocs可以找到

自动生成注释效果如下:

12ignore

项目开发中通常会使用到git进行版本管理,在提交代码时经常有人将本地的不必要的文件提交到代码仓库中,使用.ignore插件可以很好解决这个问题。插件安装完成后会在项目中生成一个.ignore文件,编辑该文件忽略一些动态生成的文件,如class文件,maven的target目录等。

13RainbowBrackets

彩虹括号,代码中有多个括号会显示不同的颜色。

14Activate-power-mode

在敲代码时有抖动酷炫的特效,非常适合给前端小姐姐表演特技。(坏笑)

15CodeGlance

16GenerateAllSetter

  • 通过alt+enter对变量类生成对类的所有setter方法的调用
  • 当两个对象具有相同的字段时生成一个转换器
  • 当returnType为List Set Map时生成默认值
  • 在所有getter方法上生成对assertThat的调用

17RestfulToolkit

  • 根据 URL 直接跳转到对应的方法定义 ( 快捷键搜索 Ctrl + Alt + N 或者 Ctrl + \ ); —这个个人感觉非常好用,和Ctrl + F一样重要。
  • 提供了一个 Services tree 的显示窗口;
  • 一个简单的 http 请求工具;
  • 在请求方法上添加了有用功能: 复制生成 URL;,复制方法参数…
  • 其他功能: java 类上添加 Convert to JSON 功能,格式化 json 数据 ( Windows: Ctrl + Enter; Mac: Command + Enter )。

18JRebel

热门部署插件,让你在修改完代码后,不用再重新启动,很实用!但是,不是免费的,需要大家发挥下聪明才智自行百度破解!

19Json Parser

厌倦了打开浏览器格式化和验证JSON?为什么不安装JSON解析器并在IDE中使用离线支持呢?JSON解析器是一个用于验证和格式化JSON字符串的轻量级插件。

20aiXcode & codota

aiXcoder是一个强大的代码完成器和代码搜索引擎,基于最新的深度学习技术。它有可能向您推荐一整套代码,这将帮助您更快地编写代码。aiXcoder还提供了一个代码搜索引擎,以帮助您在GitHub上搜索API用例。

类似功能的插件还有codota,codota基于数百万个开源Java程序和您的上下文来完成代码行,从而帮助您以更少的错误更快地进行编码。新版本的codota提供以下功能:

  • 全线AI自动完成
  • 内联和相关代码示例
  • 根据用户自己的编码实践进行编码建议
  • 不用担心你的代码会被公开。codota不会将你的代码发送到codota服务器,它只会从当前编辑的文件中发送最少的上下文信息,从而使codota能够根据你当前的本地范围进行预测。

比如我想知道list.stream.map(…)方法的参考使用,只需要光标定位在map上,然后右键选择菜单“Get relevant examples”或者使用快捷键“Ctrl + Shift + O”就可以快速搜索出来很多示例,非常方便。

来源:blog.csdn.net/CSDN_SAVIOR/article/details/122505538

作者 | Sara A. Metwalli

译者 | 有数可据

出品 | CSDN(ID:CSDNnews)

新的 Python 版本推出了有趣的新功能。

Python 是当今最流行的编程语言之一。它有广泛的领域和应用,从学习计算机科学的基础,到执行复杂或者直接的科学计算任务来创建游戏。它的高级应用甚至包含数据科学和量子计算。

Python的流行有很多原因。其中最主要的原因是Python和其他语言相比,通用性强,简单易学。除此之外,Python的开发和维护者——Python软件基金会——一直致力于用新的方法改进Python。

一周之前(2021年10月4日),一个新的Python版本发布了,Python 3.10。在新的版本中,Python 添加了独特且有价值的功能,同时删除了一些旧功能。我们可以将任何新软件版本中添加或删除的功能归为多个类别,例如语法特性、添加到默认库或对现有特性的改进。

Python 3.10 有几个新的很酷的功能,使得使用 Python 成为一种更好的体验。在本文中,我将与您分享 6 个让我最兴奋的新特性。


更清楚的错误追踪


作为一个每天写Python 、教Python 的人,我深知遇到语法错误的挫败感。尽管一旦你掌握了Python和编程,就很容易修复语法错误,但是我们还是希望错误消息能给我们更好的提示,以帮助我们更好地定位错误并节省调试时间。

在Python 3.10中,两个新特性使得我们可以更好地处理错误,他们是更清楚的错误消息以及精确的行号。比如,我们有以下代码,包含一个字典和一个函数。但是我们忘记了字典结束的花括号“}”。

some_dict={1: "jack", 2: "john", 3: "james" ,a_results=a_useful_function()

在之前的Python版本中,错误信息如下:

File "amazing_code.py", line 3 a_results=a_useful_function() ^ SyntaxError: invalid syntax # 无效的语法

但是,随着新的错误消息和行号的改进,新的错误消息将包含更好的信息,例如准确的错误类型和精确的行号。

File "amazing_code.py", line 1 expected={1: "jack", 2: "john", 3: "james" , ^ SyntaxError: '{' was never closed # 未关闭的 “ { ”

这一新特性将有助于加快调试速度,并减少人们开始学习 Python 的挫败感。


结构化模式匹配


如果您使用过 C++ 等其他编程语言,您可能希望 Python 有 switch 语句,这样您就不必经历冗长的 if、elif、elif、....、else 语句。好吧,Python 3.10 的新特性之一是添加了结构化模式匹配,或者换句话说,具有以下语法的 switch、case 语句。

match subject: case <patt1>: <act1> case <patt2>: <act2> case <patt3>: <act3> case _: <action_default>


新的类型联合运算符


尽管 Python 是一种动态类型的编程语言,但还是有一些方法可以使它的某些部分成为静态类型的。比如,你正在写一个函数,而属性的类型对于函数的内部通信很重要。在之前的版本中,你可以指定类型如下:

def func(num: int) -> int: return num + 5

但是,如果你要接受两种类型,你就需要使用Union关键字。

def func(num: Union[int, float]) -> Union[int, float]: return num + 5

在新版Python中,你可以用“|”运算符替代Union关键字,这样会更直接。

def func(num: int | float) -> int | float: return num + 5


其他很酷的特性


4.1 更严格的zip

Python的乐趣之一就是zip()函数。它是一个内置函数,允许你同时遍历多个序列,并组合其返回值。在之前的版本中,你可以对不同长度的序列使用zip。但是,现在有了一个新的参数,strict,用来检查可遍历对象是否长度一致。

4.2 自动文本编码

作为程序员,我们会说,“他在我的电脑上能运行的”。代码在一台机器上运行而不在另一台机器上运行的原因有很多;文本编码可能会导致此类错误。

在以前的 Python 版本中,如果没有明确说明编码类型,首选的本地编码可能会导致代码在其他机器上失败。在 Python 3.10 中,可以激活警告以通知用户打开文本文件没有指定编码类型。

4.3 异步迭代

异步编程是一个强大而先进的编程范式,它从 3.5 版开始就成为 Python 的一部分。在Python 3.10,有两个新的异步的内置功能aiter()和anext()使你的代码更易读。


最后的想法


当我攻读本科学位时,我参加了几门使用 C++ 或 Java 编写代码和实现应用程序的课程。但是,当我要写毕业论文时,我决定学习和使用 Python。那是差不多十年前的事了,我再也没有回头;每当我解决问题时,Python就成了我首选的编程语言。

后来,我开始教授儿童计算机科学。我意识到 Python 正激励年轻一代从事技术职业。除了容易读写,容易上手,我最喜欢Python的一点是Python软件基金会的努力工作,保持Python与时俱进。

Python的每个版本,都带来了不起的新特性。这些特性是大部分Python程序员需要的,能让我们高效写Python代码。总之,它们让人们写代码更容易。本文中,我分享了让我和我的学生兴奋的Python 3.10的六个新特性。

参考链接:

  • https://towardsdatascience.com/6-new-awesome-features-in-python-3-10-a0598e87689f

  • https://docs.python.org/3/whatsnew/3.10.html

  • https://docs.python.org/zh-cn/3/whatsnew/3.10.html