转自葱丝瓣酱-python面试问题

原文链接

没事去知乎上面搜了一下各路python大牛的博客,偶尔发现这篇,对我刚刚进阶的新手来说收获颇丰,作为感谢,想把这些好东西分享给更多的python爱好者们。

如果你喜欢这篇文章,请不要忘了关注作者!

 

以下是全文:

 

最近正在团队内部普及 Python 语言,有些刚接触 Python 语言的工程师在概念上有很多混淆的地方,刚好看到这篇文章:Python面试问题,里面列举的问题都是关于 Python 基本的常识或者容易混淆的知识点,因此推荐给团队的 Python 初学者。

  1. 参数是如何传递的?传值还是传引用?(How are arguments passed – by reference of by value?)

    这个问题的有点c/c++风格,问题的实质是当一个传入的参数在函数体内被更改,那么在函数返回后,函数体外的这个参数变量的值是否改变。最简短的回答是,”都不是”,事实上 Python 里是传对象(call by object)。

    要弄明白这个变量的值是否在函数体外发生变化,需要明白两个概念:

    • Python 里的对象分为有可变(mutable)和不可变(immutable):数字(int, float),字符串,元组(tuple)是不可变的,列表(list),字典(dict)是可变的。
    • 所有的变量都是一个对象的引用。无论对象是否可变,这个变量都可被赋值为另外一个对象。

    因此,如果传入的参数变量指向一个不可变对象,那么在函数体外这个对象的内容永远不会发生变化;如果当传入的参数变量指向一个可变对象,那么这个对象是否发生变化,取决于函数体内部是否改变了这个可变对象的内容。

    下面的例子里,changed函数调用改变了传入对象的内容,unchanged函数将l变量赋值为一个新生成的对象l = l + ["a"],但原始对象并未发生变化:

    复制代码
     1 def changed(l):
     2     l.append("a")  #  change the original object
     3 
     4 def unchanged(l):
     5     l = l + ["a"]  # l + ["a"] will create a new list, instead of changing the original object
     6 
     7 l1 = []
     8 changed(l1)
     9 # l1 == ["a"]
    10 
    11 l2 = []
    12 unchanged(l2)
    13 # l2 == []
    复制代码
  2. 什么是列表和字典推导(list and dict comprehensions)?你能给个例子吗?

    列表/字典推导是一种语法糖(syntax sugar),用来简化列表和字典的生成。根据第三版的”Learning Python”,列表推导的执行速度快于通常的循环,但并不确保以后的 Python 版本也是这个结果。

    
    
    复制代码
     1 # simple iteration
     2 a = []
     3 for x in range(10):
     4     a.append(x*2)
     5 # a == [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
     6 
     7 # list comprehension
     8 a = [x*2 for x in range(10)]
     9 
    10 # dict comprehension
    11 a = {x: x*2 for x in range(10)}
    12 # a == {0: 0, 1: 2, 2: 4, 3: 6, 4: 8, 5: 10, 6: 12, 7: 14, 8: 16, 9: 18
    13 
    14 # set comprehension
    15 a = {x**2 for x in range(10) if x % 2 == 0}
    16 # a == set([0, 16, 4, 64, 36])
    复制代码
    
    

     

    列表推导是典型的 Pythonic 的代码书写方式。

  3. 什么是 PEP 8?

    PEP 8 定义的是 Python 代码规范,告诉你如何书写可读性强,更好维护的代码。详细内容请参考PEP 8 官方文档。Sublime Text编辑工具带有 PEP 8 格式检测插件,所存盘的文件都应当符合 PEP 8 的规范。

  4. 你使用虚拟环境(virtual environment)吗?

    很多 Python 程序员认为,包括我自己也是这样的观点,virtual environment是一个非常有用的工具,用来孤立你的开发和运行环境,特别是当需要同时开发多个项目,基于不同的 Python 版本以及运行库的时候。每当新建一个项目,或者clone一个已存在项目的时候,我都会按照下面的步骤建立和使用虚拟环境:

    
    
    复制代码
     1 # create virtual env
     2 virtualenv --no-site-packages --python=python3.2 ./venv
     3 
     4 # activate virtual env
     5 source ./venv/bin/activate
     6 # install requirements
     7 pip install -r requirements.txt
     8 
     9 #.....
    10 # update requirements
    11 pip freeze > requirements.txt
    复制代码
    
    

     

  5. 如何计算列表里所有元素的和?如何计算列表里所有元素的乘积?

    这个问题相当简单,但需要记住一点,你需要用 Pythonic 的方式来解答这个问题:

    
    
    复制代码
     1 # 计算列表内所有元素的和, 包括基本loop方式,sum函数方式,以及使用reduce函数
     2 
     3 # the basic way
     4 s = 0
     5 for x in range(10):
     6     s += x
     7 
     8 # the right way
     9 s = sum(range(10))
    10 
    11 # the other way
    12 from operator import add
    13 s = reduce(add, range(10))
    14 
    15 # 计算列表内所有元素的乘积
    16 
    17 # the basic way
    18 s = 1
    19 for x in range(1, 10):
    20     s = s * x
    21 
    22 # the other way
    23 from operator import mul
    24 reduce(mul, range(1, 10))
    复制代码
    
    
  6. 你能列出列表(list)和元组(tuple)的区别吗?举例子说明用法的不同。

    列表和元组是 Python 里最基本的两个数据类型:

    • 首先,列表对象是可变的(mutable),但元组不是;
    • 其次,元组可被哈希(hashed),例如可以用作字典对象的键值(key);

    至于例子,地图上的地理坐标可以用二元组表示,而地图上的路径可以用坐标点列表来表示。

  7. 你知道rangexrange的区别吗?

    range函数返回的是一个列表对象,xrange返回的是一个xrange对象。他们的主要区别是:

    • 内存的占用不同。列表对象已经在内存中存在了,而xrange对象永远占 用同样的内存大小,无论需要生成的range有多大。
    • xrange对象不能使用列表对象的切片函数,也就是说 range(10)[3:5]能工作,但是xrange(10)[3:5]就不工作了。

    类似的问题还有:mapitertools.imap的区别?filteritertools.ifilter的区别?清楚这些区别,你就能知道怎样更有效地使用这些函数。

  8. 请说出一些 python2.x 与 python3.x 之间的区别。

    如果你经常看网上的文章,你肯定能说出一些区别:

    • python3.x 的字符串都是unicode;
    • python3.x 中print是函数,而不是语句;
    • python3.x 中使用range代替了xrange,删除了xrange函数;
    • python3.x 中全部类(class)都是新类型(new style);
    • python3.x 支持更简单的unpack方式,如first, *middle, last = [0, 1, 2, 3, 4, 5, 6, 7]

    如果你一条区别也说不出来,至少说明你对 Python 的关注度不够。

  9. 什么是修饰器(Decorator)?你能说出它的用途吗?

    修饰器(Decorator)也是一种非常 Pythonic 的方式,它可以让你非常方便地注入(inject)或者修改函数和类的代码。换句话说,修饰器允许你包装函数和类方法,在执行原始代码之前和之后执行其他 的代码。修饰器语法能带来很多非常有意思的编码方式,例如:

    • 内存缓存

      复制代码
       1 def memoize(f):
       2       memo = {}  #  将结果缓存在memo字典对象中,key是参数,value是结果。
       3       def helper(x):
       4           if x not in memo:            
       5               memo[x] = f(x)
       6           return memo[x]
       7       return helper
       8 
       9   # 修饰fib函数,任何fib函数的调用,将首先察看是否已经有缓存的结果
      10   @memoize
      11   def fib(n):
      12       if n == 0:
      13           return 0
      14       elif n == 1:
      15           return 1
      16       else:
      17           return fib(n-1) + fib(n-2)
      18 
      19   print(fib(40))  #  102334155
      复制代码
    • 参数检测

      复制代码
       1 def argument_test_natural_number(f):
       2       def helper(x):
       3           if type(x) == int and x > 0:
       4               return f(x)
       5           else:
       6               raise Exception("Argument is not an integer")
       7       return helper
       8 
       9   @argument_test_natural_number
      10   def faculty(n):
      11       if n == 1:
      12           return 1
      13       else:
      14           return n * faculty(n-1)
      15 
      16   for i in range(1,10):
      17       print(i, faculty(i))
      18   # 1 1
      19   # 2 2
      20   # 3 6
      21   # 4 24
      22   # 5 120
      23   # 6 720
      24   # 7 5040
      25   # 8 40320
      26   # 9 362880
      27 
      28   faculty(-1) # 使用非法的参数调用faculty函数,这将raise一个exception
      29   # Exception: Argument is not an integer
      复制代码
  10. with语句及其用法?

    简单地说,with语句允许你在进入和/或退出指定的代码块的时候,执行特定的代码。最常用的例子是使用with句打开文件。为了在你自己定义的对象上使用with语句,你必须定义__enter____exit__方法。

    更多的信息你可以查看理解 Python 的 with 语句


除了原文列举上述问题,下面知识点也是 Python 面试中很可能被问到的:

  • Package/Module的定义,以及模块加载原则;
  • 如何构建你自己的类型,如列表(list),字典(dict),迭代器(iterator);
  • 生成器(generator)的概念以及使用方式;
  • built-in 类型和函数;
  • 对象属性的操作原理,如dictgetattrgetattribute,描述 器(descriptor);
  • 元类编程(metaclass)的概念,以及如何使用;
  • 如何进行Package/Module的打包和分发;
  • 什么是WSGI;
  • 字符串的处理和正则表达式;
  • 如何操作json和xml数据;

另外,还必须尽可能地多了解 Python 语言最为强大的 库函数

posted @   Xander-Hang  阅读(324)  评论(1编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示