经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Python » 查看文章
Python 初学者容易踩的 5 个坑
来源:cnblogs  作者:咸鱼Linux运维  时间:2024/3/13 9:22:10  对本文有异议

哈喽大家好,我是咸鱼。

今天咸鱼列出了一些大家在初学 Python 的时候容易踩的一些坑,看看你有没有中招过。

原文:https://www.bitecode.dev/p/unexpected-python-traps-for-beginners

不明显的字符串拼接

Python 在词法分析的时候会把多个字符串自动拼接起来。

  1. data = "very""lazy"
  2. print(data) # verylazy

这个特性可以让我们在声明一个长字符串的时候可以分成多行来写,这样看起来比较优雅。

  1. msg = (
  2. "I want this to be on a single line when it prints "
  3. "but I want it to be broken into several lines in "
  4. "the code"
  5. )
  6. print(msg)
  7. # I want this to be on a single line when it prints but I want it to be broken into several lines in the code
  1. msg ="I want this to be on a single line when it prints " "but I want it to be broken into several lines in " "the code"
  2. print(msg)
  3. # I want this to be on a single line when it prints but I want it to be broken into several lines in the code

但初学者往往会忽略这一点,他们在使用包含字符串的列表时把分隔符漏掉,造成了意想不到的字符串拼接。

比如说他们想要声明一个包含域名的列表host。

  1. host = [
  2. "localhost",
  3. "bitecode.dev",
  4. "www.bitecode.dev"
  5. ]
  6. print(host) # ['localhost', 'bitecode.dev', 'www.bitecode.dev']

但是写成了下面这样。

  1. host = [
  2. "localhost",
  3. "127.0.0.1",
  4. "bitecode.dev" # 这里把逗号忘掉了
  5. "www.bitecode.dev"
  6. ]
  7. print(host) # ['localhost', 'bitecode.devwww.bitecode.dev']

这是有效的代码,不会触发语法错误,但是解析的时候会把 "bitecode.dev""www.bitecode.dev" 拼接在一起,变成 'bitecode.devwww.bitecode.dev'

sorted() 和 .sort() 傻傻分不清

在 Python 中,大多数函数或方法都会返回一个值。比如说我们要对一个列表里面的内容进行排序,可以使用 sorted() 方法。

  1. # sorted() 方法会返回一个排序后的新列表
  2. numbers = [4, 2, 3]
  3. sorted_numbers = sorted(numbers)
  4. print(sorted_numbers) # [2, 3, 4]

我们也可以用列表自带的 .sort() 方法来排序,需要注意的是: .sort() 直接对原有列表进行排序,不会返回任何值。

  1. # .sort() 方法直接对原列表进行排序
  2. numbers = [4, 2, 3]
  3. numbers.sort()
  4. print(numbers) # [2, 3, 4]

但是初学者很容易把 sorted() 的用法用在 .sort() 上,结果发现怎么返回了一个 None。

  1. numbers = [4, 2, 3]
  2. sorted_numbers = numbers.sort()
  3. print(sorted_numbers) # None

list.sort() 修改原列表,它不会返回任何内容。当 Python 可调用对象不返回任何内容时,会得到 None

或者把 .sort() 的用法用在了 sorted() 上。

  1. numbers = [4, 2, 3]
  2. sorted(numbers)
  3. print(numbers) # [4, 2, 3]

不要乱加尾随逗号

我们在创建一个空元组的时候可以用下面的两种方法:

  1. t1 = ()
  2. t2 = tuple()
  3. print(type(t1))
  4. print(type(t2))

在 Python 中,虽然元组通常都是使用一对小括号将元素包围起来的,但是小括号不是必须的,只要将各元素用逗号隔开,Python 就会将其视为元组。

  1. t1 = 1,
  2. print(t1) # (1,)
  3. print(type(t1)) # <class 'tuple'>

所以如果在数据后面多加了一个逗号,就会产生一些问题。

比如说下面是一个列表:

  1. colors = [
  2. 'red',
  3. 'blue',
  4. 'green',
  5. ]
  6. print(colors) # ['red', 'blue', 'green']

如果不小心加了一个尾随逗号,列表就变成了元组。

  1. colors = [
  2. 'red',
  3. 'blue',
  4. 'green',
  5. ],
  6. print(colors) # (['red', 'blue', 'green'],)

在 python 中,包含一个元素的元组必须有逗号,比如下面是包含一个列表的元组:

  1. colors = [
  2. 'red',
  3. 'blue',
  4. 'green',
  5. ],

这是列表:

  1. colors = ([
  2. 'red',
  3. 'blue',
  4. 'green',
  5. ])

可怕的 is

在 python 中, is 和 == 都是用来比较 python 对象的,区别是:

  • is 比较需要对象的值和内存地址都相等
  • == 比较只需要对象的值相等就行了

事实上,这两者的实际使用要远远复杂的多。

比如说下面的 a 和 b 是两个不同的对象,a is b 应该返回 False,但是却返回了 True。

  1. a = 4
  2. b = 4
  3. print(a == b) # True
  4. print(a is b) # True

在 python 中,由于小整数池和缓存机制,使用 is 来比较对象往往会出现意想不到的结果。

关于小整数池和缓存机制可以看我这篇文章:

《Python 中 is 和 == 的区别》

奇怪的引用

在Python中,如果 * 运算符用于数字与非数字型数据(列表、字符串、元组等)的结合,它将重复非数字型数据。

  1. print("0" * 3) # '000'
  2. print((0,) * 3) # (0, 0, 0)

在创建一个多个列表元素的元组时候,如果使用下面的代码:

  1. t1 = ([0],) * 3
  2. print(t1) # ([0], [0], [0])

会带来意想不到的问题:我们对元组中的第一个列表元素中的数据进行算数运算(自增 1)

  1. t1[0][0] += 1
  2. print(t1) # ([1], [1], [1])

我们发现元组中的所有列表元素内的数据都自增 1 了,我们不是只对第一个列表元素进行自增的吗?

实际上,当我们执行 t1 = ([0],) * 3 的时候,不会创建一个包含三个列表组成的元组,而是创建一个包含 3 个 引用的元组,每个引用都指向同一个列表。

元组中的每个元素都是对同一个可变对象(列表)的引用,所以当我们修改其中的元素时,另外的对象也会跟着发生变化。

正确的方法应该是:

  1. t2 = ([0], [0], [0])
  2. # 或者 t2 = tuple([0] for _ in range(3))
  3. t2[0][0] += 1
  4. print(t2) # ([1], [0], [0])

在 python 的其他地方中也有这种类似的坑:

  1. def a_bugged_function(reused_list=[]):
  2. reused_list.append("woops")
  3. return reused_list
  4. print(a_bugged_function()) # ['woops']
  5. print(a_bugged_function()) # ['woops', 'woops']
  6. print(a_bugged_function()) # ['woops', 'woops', 'woops']

可以看到,reused_list 在函数定义中被初始化为一个空列表 [],然后每次函数调用时都使用这个默认的空列表。

在第一次调用 a_bugged_function() 后,列表变成了 ['woops']。然后,在第二次和第三次调用中,它分别继续被修改,导致输出的结果为:

  1. ['woops']
  2. ['woops', 'woops']
  3. ['woops', 'woops', 'woops']

这是因为在函数定义中,如果将可变对象(例如列表)作为默认参数,会导致该对象在函数调用时被共享和修改:每次调用函数时,使用的都是同一个列表对象的引用。

为了避免这种情况,常见的做法是使用不可变对象(如 None)作为默认值,并在函数内部根据需要创建新的可变对象。

  1. def a_fixed_function(reused_list=None):
  2. if reused_list is None:
  3. reused_list = []
  4. reused_list.append("woops")
  5. return reused_list
  6. print(a_fixed_function())
  7. print(a_fixed_function())
  8. print(a_fixed_function())

原文链接:https://www.cnblogs.com/edisonfish/p/18066829

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号