
刚学 Python 的小伙伴是不是经常遇到一些让人摸不着头脑的错误?明明代码看起来差不多,可就是运行不了。别担心,今天就来给大家盘点 5 个 Python 新手常踩的坑,帮你提前避雷,少走弯路。
很多刚学 Python 的新手会觉得,元组嘛,就是用括号括起来的东西。其实呀,这是个大大的误解。元组的关键可不是括号,而是逗号!
比如说,你要是写个(1),那 Python 会把它当成一个普通的整数 1,而不是元组。但你写成(1,),这才是一个真正的元组。括号只是用来明确优先级或者让代码看起来更美观的,避免和数学表达式搞混。
咱们来看段代码感受一下:
# 这不是元组
a = (1)
print(type(a)) # 输出:<class 'int'>
# 这才是元组
b = (1,)
print(type(b)) # 输出:<class 'tuple'>
# 没有括号也能是元组
c = 2, 3
print(type(c)) # 输出:<class 'tuple'>面试官可能会问:“如何定义一个只有一个元素的元组?”
回答:定义单个元素的元组时,要在元素后面加上逗号,比如(5,)。因为元组的关键是逗号,而不是括号,只写(5)的话,Python 会把它当成整数 5。
Python 和很多其他编程语言不一样,它是靠缩进来区分代码块的。这就导致很多新手在复制粘贴代码的时候,很容易出现缩进混乱的问题,进而引发 IndentationError。
那怎么避免这个问题呢?最好的办法就是让编辑器自动格式化代码,而且要统一使用空格来缩进,别用制表符。不同的编辑器可能有不同的设置,大家可以去研究一下自己用的编辑器怎么设置自动格式化。
咱们看个例子:
# 正确的缩进
if 5 > 3:
print("5大于3")
print("没错吧")
# 错误的缩进
if 5 > 3:
print("5大于3")
print("这里缩进不对") # 会报错 IndentationError面试官可能会问:“Python 中缩进的作用是什么?不规范的缩进会导致什么问题?”
回答:在 Python 中,缩进是用来区分代码块的,像 if 语句、循环语句等后面的代码块都需要通过缩进来标识。不规范的缩进会导致 IndentationError,让程序无法正常运行,因为 Python 无法正确判断代码之间的逻辑关系。
很多新手会把 is 和 == 搞混,觉得它们是一样的,其实不然。
== 是用来比较两个对象的值是否相等;而 is 是用来比较两个对象的内存地址是否相同,也就是判断它们是不是同一个对象。
在一些情况下,比如小整数(像 100),由于 Python 的缓存机制,可能会让两个变量指向同一个对象,这时候用 is 也会返回 True。但对于浮点数、字符串等,这种情况就不一定了,所以用 == 来比较值更安全。
看段代码就明白了:
a = 100
b = 100
print(a == b) # 输出:True
print(a is b) # 输出:True,因为小整数有缓存
c = 2000
d = 2000
print(c == d) # 输出:True
print(c is d) # 输出:False,大整数没有缓存
e = "hello"
f = "hello"
print(e == f) # 输出:True
print(e is f) # 可能输出True也可能输出False,不确定面试官可能会问:“is 和 == 有什么区别?在什么情况下应该用 is,什么情况下应该用 ==?”
回答:is 用于比较两个对象的内存地址是否相同,也就是判断它们是不是同一个对象;== 用于比较两个对象的值是否相等。当我们需要判断两个变量是否指向同一个对象时,用 is;当我们只需要判断两个对象的值是否相等时,用 ==。一般来说,比较值的时候用 == 更安全。
很多新手写 Python 模块的时候,不注意主函数入口,结果在导入模块的时候,模块里的代码会被执行,造成不必要的麻烦。
这时候,加上 if name == "main" 就很有必要了。它能确保当脚本作为主程序运行时,才执行里面的测试逻辑;而当这个脚本被当作模块导入时,里面的代码不会被触发,这样能让代码更整洁。
举个例子:
# 模块文件:my_module.py
def add(a, b):
return a + b
# 没有主函数入口的情况,导入时会执行下面的代码
print(add(2, 3)) # 当被导入时也会执行
# 有主函数入口的情况
if __name__ == "__main__":
print(add(3, 4)) # 只有作为主程序运行时才会执行当我们在另一个文件中导入 my_module 时:
import my_module
# 如果my_module.py中没有主函数入口,导入时会打印5;有主函数入口则不会
result = my_module.add(1, 2)
print(result) # 输出:3面试官可能会问:“if name == "main" 的作用是什么?”
回答:这个语句的作用是判断当前模块是否作为主程序运行。当模块被直接运行时,name变量的值会是 "main",这时里面的代码块会被执行;当模块被导入到其他程序中时,name变量的值是模块的名字,里面的代码块就不会被执行。它可以让模块在作为脚本运行时执行一些测试代码,而在被导入时不执行,使代码结构更清晰。
在 Python 的面向对象编程中,类属性和实例属性是很容易被新手混淆的概念。
类属性是在类中直接定义的变量,它不属于任何一个实例,而是被所有实例共享。实例属性是通过 self.xxx 定义的变量,每个实例都有自己独立的实例属性。
如果混淆了这两者,就可能导致数据被意外共享或覆盖。
我们来看个例子:
class Person:
# 类属性
species = "human"
def __init__(self, name):
# 实例属性
self.name = name
# 创建两个实例
p1 = Person("张三")
p2 = Person("李四")
# 访问类属性,所有实例共享
print(p1.species) # 输出:human
print(p2.species) # 输出:human
print(Person.species) # 输出:human
# 访问实例属性,每个实例独立
print(p1.name) # 输出:张三
print(p2.name) # 输出:李四
# 修改类属性
Person.species = "people"
print(p1.species) # 输出:people,所有实例的类属性都变了
print(p2.species) # 输出:people
# 修改p1的实例属性
p1.name = "王五"
print(p1.name) # 输出:王五
print(p2.name) # 输出:李四,不影响p2的实例属性为了更清晰地对比类属性和实例属性,我们用一个表格来展示:
属性类型 | 定义方式 | 特点 |
|---|---|---|
类属性 | 在类中直接定义,不通过 self | 所有实例共享,属于类本身 |
实例属性 | 在init方法中通过 self.xxx 定义 | 每个实例独立拥有,不同实例的实例属性互不影响 |
多态是面向对象编程的重要特性之一,它指的是不同的对象对同一消息做出不同的响应。在 Python 中,多态的实现比较灵活,不需要像一些其他语言那样有严格的继承关系约束。
比如说,我们有一个动物类,还有狗和猫两个子类,它们都有 “叫” 这个方法,但叫的方式不同。当我们调用 “叫” 这个方法时,狗会 “汪汪叫”,猫会 “喵喵叫”,这就是多态的体现。
class Animal:
def make_sound(self):
pass
class Dog(Animal):
def make_sound(self):
print("汪汪汪")
class Cat(Animal):
def make_sound(self):
print("喵喵喵")
def animal_sound(animal):
animal.make_sound()
# 创建实例
dog = Dog()
cat = Cat()
# 调用函数,体现多态
animal_sound(dog) # 输出:汪汪汪
animal_sound(cat) # 输出:喵喵喵在上面的代码中,animal_sound 函数接收一个 Animal 类型的参数(实际上只要有 make_sound 方法的对象都可以),然后调用它的 make_sound 方法。当传入 Dog 实例时,会执行 Dog 类中的 make_sound 方法;传入 Cat 实例时,会执行 Cat 类中的 make_sound 方法。这就是多态,同一个函数调用,根据传入的对象不同,产生了不同的结果。
面试官可能会问:“请解释一下类属性和实例属性的区别,以及 Python 中的多态是如何实现的?”
回答:类属性是在类中直接定义的,被所有实例共享;实例属性是通过 self 在init方法中定义的,每个实例独立拥有。Python 中的多态不需要严格的继承关系,只要不同的对象有相同的方法名,就可以对同一消息做出不同响应。比如不同的类都定义了同一个方法,当调用这个方法时,不同的类实例会执行各自类中的方法,这就是多态的体现。
以上就是 Python 新手经常犯的 5 个错误,希望大家在学习过程中能注意这些问题,少走弯路。编程学习就是一个不断踩坑、不断总结经验的过程,只要多练习、多思考,就能越来越熟练。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。