社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

有10w+的人,搞不懂这几个 Python 问题

Python编程时光 • 4 年前 • 515 次点击  

本文挑选了全球第二大同性交友网站StackOverflow上被点赞最多的10个问题,其中总点赞数超过了5万,考虑到很多白嫖党,至少有10万人对这些问题感兴趣!

这么多人点赞,说明两个问题:

  1. 这些问题很常用,编程的时候经常碰到
  2. 这些问题不简单,否则不用去论坛上文

10个问题,看看你会几个?

  1. Yield关键词是做什么的?
  2. ifname== 'main'是做什么的 ?
  3. Python有三元运算符吗?
  4. Python的metaclasses是做什么的?
  5. 如果在不出异常的情况下检查文件是否存在?
  6. 如何一句话合并两个字典?
  7. Python如何调用外部命令,比如启动QQ?
  8. 如何安全的创建一个多层文件夹?
  9. 循环中如何访问下标?
  10. staticmethod和classmethod的区别?

这10个问题,有的复杂,有的简单。你会几个呢?可以在评论区留言。

我原本打算讲解10个问题,但由于篇幅原因,本文只涵盖了被问最多的一个问题,后续文章可能会涵盖多个问题。

下面我们重点看第一个问题:

yield关键词是做什么的?

这个问题是所有Python问题的排名第一:

  1. 有10000多人对问题点赞,表示有同样疑问。
  2. 其中高赞回答有15000多点赞。
  3. 有超过2百40万的浏览。

我曾经录制过一个关于Yield关键词的视频,自认为比高赞答案还要更清楚一点,建议视频和答案一起看。

问题详细内容?

Yield关键词是做什么的?

比如下面的代码:

def _get_child_candidates(self, distance, min_dist, max_dist):
    if self._leftchild and distance - max_dist         yield self._leftchild
    if self._rightchild and distance + max_dist >= self._median:
        yield self._rightchild  

这是调用的代码:

result, candidates = [], [self]
while candidates:
    node = candidates.pop()
    distance = node._get_dist(obj)
    if distance <= max_dist and distance >= min_dist:
        result.extend(node._values)
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
return result

当_get_child_candidates被调用时,发生了什么?返回了一个list吗?还是一个元素?它会被反复调吗?后续调用什么时候停止?

看着有点懵?可以继续往下看解答,然后再回来看问题。

最高赞回答 (15000多赞)

要理解yield,先理解generators,要理解generators先理解iterable(可迭代的)。

Iterables

当你创建1个list,你可以一个个读取它的值,这叫做迭代:

>>> mylist = [123]
>>> for i in mylist:
...    print(i)
1
2
3

上面mylist是一个iterable(可以被迭代的)。当你使用一个列表推导式,你创建了一个列表,也就是一个iterable:

>>> mylist = [x*x for x in range(3)]
>>> for i in mylist:
...    print(i)
0
1
4

所以可以使用for...in...语法遍历的就是iterable:list, str, file等等

这些iterable很有用,你可以循环访问他们。但是它们所有的值都保存在内存中。如果你的list中有10亿个字符串的时候,创建这个list会很慢,而且会很占用内存,所以我们需要Genertor.

Generators

Generator是iterable,可以被循环。但和上面不一样,它一般只能被循环一次。它不会把所有的值保存在内存中,他们在循环中动态产生元素的值。

>>> mygenerator = (x*x for x in range(3))
>>> for i in mygenerator:
...    print(i)
0
1
4

这个生成器和列表推导式几乎一样,唯一区别使用小括号(),而不是中括号[]. 但,你不能两次使用for i in mygenerator,因为生成器只能被循环一次:他们计算0x0,返回结果,自己并不保存,下一次调用它,他计算1x1,以此类推。

Yield

Yields是一个关键词,可以先理解成和return一样,区别是它返回一个generator.

>>> def createGenerator():
...    mylist = range(3)
...    for i in mylist:
...        yield i*i
...
>>> mygenerator = createGenerator() # create a generator
>>> print(mygenerator) # mygenerator is an object!
0xb7555c34>
>>> for i in mygenerator:
...     print(i)
0
1
4

上面这个例子先创建了range,已经占用了内存,但平方数没有占用。这个例子不是很好,这是原作者举的,我的视频中应该有更好的例子。

首先,因为yield的存在,当你调用上面的函数,里面的代码并没有执行,而不是返回了一个Generator。

然后是关键的地方:

  • 当for循环第一次调用generator的时候,它会从头开始执行,直到yield关键词,返回第一个值,也就是0。
  • 然后记住执行到哪一行代码,也就是yield的位置。
  • 下次for循环再次调用它,它从yield的下一行继续执行,直到再次碰到yield,返回下一个值,也就是1.
  • 这个过程一直重复,直到generator中没有内容了。例子中就是range里的数字被用完。

现在再看看最开始的问题:

这是一个对树的遍历算法,查找树上符合条件的节点。代码中加了详细的中文注释。

Generator:

# 这个函数会返回一个生成器(Generator),这是一个二叉树的node对象中的方法
def _get_child_candidates(self, distance, min_dist, max_dist):

    # 如果还有左孩子,并且距离符合条件,返回左孩子,然后暂停在这里
    if self._leftchild and distance - max_dist         yield self._leftchild

    # 如果还有右孩子,并且距离符合条件,返回右孩子,然后暂停在这里
    if self._rightchild and distance + max_dist >= self._median:
        yield self._rightchild

    # 如果执行到了这里,说明没有符合条件的左右孩子了,生成器空了,就迭代结束了。

Caller:

# 创建一个空的列表,和当前对象节点
result, candidates = list(), [self]

# 循环,开始里面只有自己
while candidates:

    # 弹出最后一个节点
    node = candidates.pop()

    # 获得obj对象和目标节点的距离
    distance = node._get_dist(obj)

    # 如果距离ok,写入到结果列表中
    if distance <= max_dist and distance >= min_dist:
        result.extend(node._values)

    # 把自己的子节点加入到candidates中,这样循环会继续,直到树上的所有节点都被遍历
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))

return result


- EOF -

推荐阅读  点击标题可跳转
用 Python自动玩王者荣耀,简直太秀了!
调试Python代码,可别再用Print了!
大一新生开源Python可视化工具,火了!
一篇文章教你如何用Python记录日志
让许多Python“老玩家”心寒的10大槽点
73个f-string的例子,帮你吃透字符串格式化


得本文对你有帮助?请分享给更多人
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/107063
 
515 次点击