Python最佳实践和技巧

Share

本资源包含由Toptal网络成员提供的Python最佳实践和Python技巧的集合.

本资源包含由Toptal网络成员提供的Python最佳实践和Python技巧的集合. As such, 本页将定期更新,以包含更多信息并涵盖新兴的Python技术. 这是一个社区驱动的项目, 所以我们也鼓励你们做出贡献, 我们期待着你们的反馈.

Python是一种用于许多开发领域的高级语言, 比如web开发(Django), Flask), data analysis (SciPy, scikit-learn), desktop UI (wxWidgets, PyQt)和系统管理(Ansible, OpenStack). Python的主要优点是开发速度快. Python自带丰富的标准库,大量第三方库和干净的语法. 所有这些都使开发人员能够专注于他们想要解决的问题, 而不是语言细节或重新发明轮子.

Check out the Toptal resource pages 以获取有关Python的更多信息. There is a Python hiring guide, Python job description, common Python mistakes, and Python interview questions.

使用Git时处理Pyc文件.

对象自动生成字节码,Python开发人员对此很熟悉 .py 文件,由解释器执行. 该字节码存储在 .pyc 文件,通常在其各自源文件的同一目录中. The .pyc 生成可以在执行主Python脚本时发生,也可以在第一次导入模块时发生.

例如,在许多Python web框架中,当我们创建 views.py,一个包含视图逻辑的文件,我们很可能会得到一个 views.pyc 在运行应用程序的实例后,在同一目录下创建.

As developers, 我们经常使用Git处理大型代码库, 以及团队中有许多开发人员的项目. 这意味着同时开发了许多功能, 因此,我们必须频繁切换分支以与其他开发人员配对, 或者检查和测试别人的代码. 根据两个分支之间的差异,我们可以得到 .pyc 来自其他分支的文件,这可能导致意外的行为.

Git是一个著名的源代码管理工具,它巧妙地提供了钩子, 一种在发生某些重要操作时触发自定义脚本的方法. 我们可以为最常用的操作添加钩子, 比如在犯罪之前或之后, pushing, rebasing, merging, and similar.

其中一个可用的钩子是“post-checkout”钩子, 哪个在签出另一个分支或特定提交后被触发. 我们可以包含我们的代码来清理 .pyc “签出后”钩子中的文件. All Git projects have .git 文件夹在项目的根目录下,从那里我们只需要编辑(或创建新的)文件 .git /钩/ post-checkout,添加以下代码:

#!/bin/sh
find . -type f -name "*.py[co]" -delete
find . -type d -name "__pycache__" -delete

这是针对Linux和Mac的. 在Windows上,首先我们需要安装Cygwin,这样Git才能以shell的形式执行钩子脚本. 然后我们需要稍微改变一下命令:

#!/bin/sh
find . -type f -name "*.py[co]" | xargs rm
find . -type d -name "__pycache__" | xargs rm -rf

调用Python解释器时 -O 标志,优化后的代码生成并存储在 .pyo files. 因此,我们的命令检查 .pyc or .pyo 文件和删除它们(*.py[co]). Python 3将编译后的字节码存储在 __pycache__ 目录,所以我们包含了一个命令来删除它们.

In the end, 在Linux和Mac上保存钩子文件后, 我们需要确保给它添加了执行权限:

$ chmod +x .git /钩/ post-checkout

Contributors

Ivan Neto

自由Python开发人员

Brazil

Ivan是一名工程师,在软件和网络开发方面有八年的经验. 主要专注于网络, 他解决了成长系统中出现的代码优化问题, 以及迁移的生产应用程序和服务的零停机时间. 虽然他的大部分经验都是在后台, 他还可以处理前端, databases, networking, and infrastructure.

Show More

从Toptal获取最新的开发人员更新.

订阅意味着同意我们的 privacy policy

为什么要避免使用“try: except: pass”模式?

与设计模式完全相反的是什么? 它是一种反模式,一种无声地破坏代码效率的模式. 我们将要描述的模式就是其中之一. Aaron Maxwell calls it 最邪恶的Python反模式:

try: 
    微妙_buggy_operation() #最可能是一些I/O或DB操作
except:
    pass

您可能认为这样可以节省一些开发时间 pass用" just for now "代替例外. But it will take hours, if not days, 在此代码块中查找以后的错误, 因为任何例外都会被掩盖 pass,并且错误位置将被移动并抛出到此之外的其他地方 try:except 块,这可能看起来像最无辜的代码.

A quote from Aaron:

在我近十年用Python编写应用程序的经验中, 无论是作为个人还是作为团队的一部分, 这种模式是开发人员生产力和应用程序可靠性的最大消耗, 尤其是从长期来看.

如果你真的想传递一两个意料之中的异常, 然后让它显式而不是全部通过. In Python, “显式优于隐式,就像下面的代码示例一样:

try: 
    微妙_buggy_operation() #最可能是一些I/O或DB操作
除了ThouShaltPassError:
    pass

Again, referencing “Zen of Python”:

错误不应该无声地传递

除非被明确噤声

Contributors

Khaled Monsoor

后端工程师(自由职业者)

python软件开发人员. Big-data enthusiast. 摄影和咖啡爱好者.

如何处理基于哈希表的操作?

许多人对Python中几乎所有基于哈希表的操作都是原地完成的这一事实感到困惑, 而不返回对象本身. 例如,他们通常会记住 dict.update() 以及几乎所有对集合的操作:

>>> a = {1,2,3}
>>> a.update({5,6,7}) #返回None
>>> a
Set ([1,2,3,5,6,7]) # object changed in place
>>> a.add(8)  # returns None
>>> a
Set ([1,2,3,5,6,7,8]) # object changed in place
>>> d = {"foo": "bar"}
>>> d.update({"zzz": "derp"}) #返回None
>>> d
{'foo': 'bar', 'zzz': 'derp'} #对象更改到位

考虑一个更实际的例子,你不能这样写:

requests = [
    web.Request(
        body=json.dumps(
            item.update({"foo": "bar"})
        )
    )中my_long_iterable中的item
]

上面的代码将每个请求的主体设置为字符串 null这可能会导致奇怪的bug或更糟糕的惊喜.

通常,大多数程序员会在思考之后将其重写为一个简单的循环:

requests = []
对于my_long_iterable中的item:
	body = item.update({"foo": "bar"})
	requests.append(
		web.Request(body=json.dumps(body))
	)

有趣的是,仍然有可能将其写成单个列表推导式. Here is how:

requests = [
    web.Request(
        body=json.dumps(
            dict(foo="bar", **item)
        )
    )中my_long_iterable中的item
]

简单易懂,对吧?

虽然,我知道有些人说循环版本更明显和可读. 在处理大量数据的情况下, 我们可以把方括号换成通常的圆括号(就像大卫·比斯利经常建议的那样), 我们的代码变成了一个惰性生成器表达式. Not to mention, 在处理循环版本时,我们需要将其移动到单独的生成器函数中, with “yield” and stuff, 这有时会导致更糟糕的可读性. You can read more from 大卫本人对这个话题的看法.

Contributors

Nikolay Markov

自由Python开发人员

Russia

Nikolay是一名软件工程师,精通Python、算法和数据结构. 他在可伸缩和高负载系统架构(Web技术)方面有经验, NoSQL, OpenStack -以及领导开发团队的经验.

Show More

我应该使用条件处理的例外吗?

Python的最佳实践是使用异常作为处理“异常”情况的更好方法. Unnecessary use of if可能会减慢代码的速度. 不过,要记住频繁的“except”呼叫 are even slower than plain if 条件处理,所以你必须明智地使用它.

总而言之,异常对于罕见的用例是好的,而条件对于频繁的用例是好的. In the end, of course “请求原谅总比请求允许好”.

Contributors

Nikolai Golub

自由Python开发人员

Netherlands

尼古拉是一个自我指导和有条理的专业人士. 他是一个以结果为导向的问题解决者,具有敏锐的分析能力和出色的沟通技巧. 他是一位非常有能力的软件工程师,在Python编程和web技术方面有四年的经验.

Show More

使用Python属性而不是显式的getter和setter

Python properties (@property)比getter和setter要干净得多. 让我们看一下下面的代码片段,用java风格编写,带有getter和setter:

class A:

  Def __init__(self, some)
    self._b = some

  def get_b(self):
    return self._b

  def set_b(self, val):
    self._b = val

a = A('123')
print(a.get_b())
a.set_b('444')

现在将此代码与使用python风格属性编写的代码进行比较:

class A:

  Def __init__(self, some)
    self._b = some

  @property
  def b(self):
    return self._b

  @b.setter
  Def b_setter(self, val):
    self._b = val

a = A('123')
print(a.b)
a.b = '123'

Please be aware, 如果在属性后面封装了复杂的逻辑或繁重的计算, 您可能会使将要使用您的类的其他开发人员感到困惑.

Contributors

Nikolai Golub

自由Python开发人员

Netherlands

尼古拉是一个自我指导和有条理的专业人士. 他是一个以结果为导向的问题解决者,具有敏锐的分析能力和出色的沟通技巧. 他是一位非常有能力的软件工程师,在Python编程和web技术方面有四年的经验.

Show More

如何比较两个对象使用' == '操作符?

如果一个类不提供 __eq__ 方法时,Python将比较两个对象并返回 True 只有当两个对象实际上是同一个对象时才值:

class A:

  def __init__(self, i):
    self.i = i

a = A(1)
b = a
c = A(1)

a == b # True
a == c # False

在本例中,对象 a and c are False,即使它们内部存储相同的值.

如果您想为两个对象启用自己的比较逻辑,并使用 == 算子,你可以实现 __eq__ method:

class Car(object):

  Def __init__(self, hor_power, color):
    self.horse_power = power
    self.color = color

  Def __eq__(self, other):
    return self.horse_power == other.horse_power and self.color == other.color

Contributors

Nikolai Golub

自由Python开发人员

Netherlands

尼古拉是一个自我指导和有条理的专业人士. 他是一个以结果为导向的问题解决者,具有敏锐的分析能力和出色的沟通技巧. 他是一位非常有能力的软件工程师,在Python编程和web技术方面有四年的经验.

Show More

感受Python逻辑操作数的力量.

Python的逻辑运算不只是返回布尔值 True or False,它们也可以返回操作的实际值.

Python逻辑操作数的强大功能可用于加快开发速度并提高代码的可读性. 在下面的例子中, 对象将从缓存中获取, 或者如果它在缓存中丢失,它将从数据库中获取:

# check_in_cache返回object或None
def get_obj(): 
返回check_in_cache()或pull_from_db()

快速解释一下所提供的示例:它将首先尝试从缓存(check_in_cache() function). 如果它没有返回对象,而是返回 None 相反,它将从数据库(pull_from_db() function). 以这种方式编写比以下以标准方式编写的代码片段更好:

def get_obj():
Result = check_in_cache()
if result is None:
  		result = pull_from_db()
	return result

我们的第一个代码示例在一行代码中解决了一个问题, 哪个比第二个代码示例中的四行代码更好. 更不用说第一个代码示例更具表现力和可读性.

只需注意一件事—您应该注意返回具有逻辑等价的对象 False,比如空列表. If check_in_cache() 函数返回这样一个对象,它将被视为丢失,并将导致应用程序调用 pull_from_db function. So, 在函数可能返回这类对象的情况下, 考虑使用额外的显式 is None check.

Contributors

Nikolai Golub

自由Python开发人员

Netherlands

尼古拉是一个自我指导和有条理的专业人士. 他是一个以结果为导向的问题解决者,具有敏锐的分析能力和出色的沟通技巧. 他是一位非常有能力的软件工程师,在Python编程和web技术方面有四年的经验.

Show More

为什么写文档或内联注释很重要?

许多开发人员认为避免用半混淆的代码编写注释可以节省时间. 或者,他们认为避免文档字符串可以帮助他们完成最后期限. 请放心,在很短的时间内,当您在阅读自己的代码时不记得自己做了什么以及为什么做某事时,您会讨厌自己.

In the future, 也许你会离开这家公司, 你的代码会困扰所有遇到这种僵尸代码的团队成员. 没有理由不写文档. 编写一个文档字符串和对复杂代码段的注释不会花费太多时间. 编写代码的另一种方法是为函数命名, 方法和变量来反映组件的目的, 让它们“自我记录”.

这里有一个很好的指导如何正确 记录你的Python代码.

Contributors

Khaled Monsoor

后端工程师(自由职业者)

python软件开发人员. Big-data enthusiast. 摄影和咖啡爱好者.

为什么你应该避免使用“从模块导入*”在你的项目?

使用a的做法 from module import * 在你的代码中可以把漂亮干净的模块变成一场噩梦. 这种做法在小项目中不会造成麻烦, 由一个小团队开发的多达10个模块组成. 但是当项目发展成一个中等规模的项目时, 工作团队分布在多个地点的多个团队中, 使用这种做法的代码将开始看到由于循环引用而产生的令人困惑的错误.

根据核心Python开发人员的说法 David Goodger:

The from module import * 通配符风格会导致名称空间污染. 您将在本地名称空间中获得您没有期望得到的东西. 您可能会看到导入的名称掩盖了模块定义的本地名称. 你将无法弄清楚某些名字的来源. 虽然这是一个方便的快捷方式,但不应该在生产代码中使用.

让我们用例子来说明. 如前所述,最糟糕的用例是以下代码:

从module_name导入*
# ...
垃圾邮件= function(foo, bar)

一个更好的用例应该符合以下代码:

从module_name导入函数
# ...
垃圾邮件= function(foo, bar)

The best 使用import模块的可能方法如下:

将module_name作为mn导入
spam = mn.function(foo, bar)

Contributors

Khaled Monsoor

后端工程师(自由职业者)

python软件开发人员. Big-data enthusiast. 摄影和咖啡爱好者.

不要把每件事都变成类.

在Python中,过度使用类并将所有东西都变成类被认为是一种不好的做法. Jack Diederich in his talk at PyCon 2012他指出,开发人员应该停止时不时地创建类和模块. 在创建一个之前,开发者应该认真思考. 最有可能的是,使用函数会更好.

如前所述,阅读 Zen of Python:

  • 美总比丑好
  • 显式优于隐式
  • 简单总比复杂好
  • 平的比嵌套的好
  • Readability counts
  • 如果实现很难解释,那就是一个坏主意

让我们用几个例子来说明这一点. 在下面的代码片段中, 尽管它是一个完全有效的类, 这是无用使用类的完美例子:

问候类(对象):
    Def __init__(self, greeting='hello'):
        self.greeting = greeting
 
    def greet(self, name):
        return '%s! %s' % (self.greeting, name)
 
greeting = greeting ('hola')
print greeting.greet('bob')

这些代码可以通过使用函数以更有效的方式重写, 如下面的代码所示:

Def greet(问候,目标):
    return '%s! %s' %(问候,目标)

Jack Diederich在他的演讲中展示了一个他如何简化的实际例子, or better re-factored, an API’s complete code, consisting of:

  • 1 Package, 22 Modules
  • 20 Classes
  • 660源代码行

进入下面的代码,总共8行. 是的,你没看错,只有8行代码:

MUFFIN_API = url='http://api.wbsrvc.com/%s/%s/'
Muffin_api_key = ' secret-api-key '
 
Def请求(名词,动词,**参数):
    headers = {'apikey': MUFFIN_API_KEY}
    request = urllib2.请求(MUFFIN_API %(名词,动词),
                              urllib.urlencode (params),标题)
    return json.loads(urllib2.urlopen(request).read())

最后:不要再重复发明轮子了, 使用更多的内置库函数, 并且使用更少的类层次结构长链.

Contributors

Khaled Monsoor

后端工程师(自由职业者)

python软件开发人员. Big-data enthusiast. 摄影和咖啡爱好者.

请编写单元测试和文档测试.

为了快速发布而避免编写自动化测试是一种不好的做法. Sooner or later, 虫子会撞到表面, 这将发生在生产服务器上, 导致客户的停机时间. 只是因为一个“完全”手动测试的新功能, 这将打破一些“几乎”不相关的东西. 也许经过许多个不眠之夜的开发团队,bug会被发现. But it will be too late.

后果可能是灾难性的,一家公司甚至可能损失数百万美元 can be out of business.

如果开发人员能够使用最佳的写作实践,也许这整个混乱可以简单地避免 unit tests and doctests. 在实现了新编写的功能之后, 他会在整个项目中运行一次测试.

The online book Dive into Python 3 对单元测试有很好的介绍吗. 另一个好的开始是 Python漫游指南!.

Contributors

Khaled Monsoor

后端工程师(自由职业者)

python软件开发人员. Big-data enthusiast. 摄影和咖啡爱好者.

在Python-Verse中,“try: except: else”结构是一个自然的控制流.

如果你是从c++或Java世界来的,周围的困惑 try: except: else is natural. 然而,Python采用这种结构与c++或Java有很大不同. In Python, try: except: else 构造被认为是一个很好的实践,因为它有助于实现Python的核心哲学之一:请求原谅比请求允许容易”, or “EAFP paradigm”.

试图避免这种做法将导致混乱的非python代码. On the StackOverflow核心Python开发人员Raymond Hettinger描述了其背后的哲学:

在Python世界中,使用异常进行流控制是常见和正常的. 即使Python核心开发人员也使用异常进行流控制,这种风格已经深深地融入到语言中.e. 迭代器协议使用StopIteration来表示循环终止). In addition, try-except样式用于防止某些“先看后跳”构造中固有的竞争条件.

For example, testing os.path.“存在”导致的信息在您使用它时可能已经过时. Likewise, Queue.Full返回可能过时的信息. 在这些情况下,try-except-else风格将产生更可靠的代码. 在其他一些语言中,这一规则反映了他们的文化规范,这些规范反映在他们的图书馆中. 该“规则”还部分基于对这些语言的性能考虑.

你也可以考虑看看这个 Q&A on StackOverflow on the same premise.

Contributors

Khaled Monsoor

后端工程师(自由职业者)

python软件开发人员. Big-data enthusiast. 摄影和咖啡爱好者.

为什么要使用生成器推导式?

By using parentheses () 而不是方括号 [] 对于推导式,我们告诉Python使用生成器而不是创建列表. 如果不需要完整的列表,这将非常有用, 或者由于列表的某些组合很长而导致编译成本很高, each object being big, 或者条件运算很昂贵.

我的主要生成器理解用例是, 在撰写本文时, 当我想在某些条件下从一组对象中得到一个对象时, 当我期望许多对象满足条件句,但我只需要一个. 就像下面的例子:

short_list = range(10)
%%timeit
y = [x for x in short_list if x > 5][0]

1000000个循环,最佳3:601 ns每循环

方括号告诉Python编译整个列表 [6, 7, 8, 9] and then pick off the 0th element. 名单这么小,没什么大不了的.

现在让我们看看下面的例子:

short_list = range(10)
%%timeit
y = (x for x in short_list if x > 5).next()

1000000个循环,每循环最好3:910 ns

括号告诉Python这是另一个推导式,而是为它创建一个生成器. That is, 设置一个可迭代对象,以便它可以用来生成与上面相同的列表, 但只要你说出来就行. The .next() 告诉生成器生成第一个值. 因为只有第一个值(6 在这种情况下)被关闭并保存,发电机离开,剩下的 7, 8, and 9 are never computed.

考虑到数据的小和额外的开销, 这比简单地使用列表要慢. 但让我们来看看更长的列表会发生什么:

Long_list = range(100000)
%%timeit
y = [x for x in long_list if x > 5][0]

100圈,最好3:6.35 ms per loop

同样,这个列表推导首先生成完整的列表 [6, 7, 8, … 99998, 99999],然后选择第一个值.

使用生成器推导式的相同示例:

Long_list = range(100000)
%%timeit
y = (x for x in long_list if x > 5).next()

1000000个循环,最好的3:931 ns每循环

和前面一样,生成器推导式只是设置一个迭代器. 向该迭代器请求它的第一个值 .next(). 然后生成器运行,直到它能够交付第一个值. It checks 0,它不符合条件. It proceeds to check 1, which again fails. 它继续查找,直到找到第一个传递条件表达式的值, 6),返回并保存到 y. 其余的99993个值从不检查,它们的性能只比 short_list 长度为10,比 long_list 使用列表推导式.

Contributors

Allen Gary Grimm

自由Python开发人员

United States

艾伦被抽象与现实的交集所吸引,他在数据科学中找到了自己的使命. 在机器学习方面接受过正式培训,在将机器学习作为原型应用到生产过程中具有广泛的经验, 他的专长是为复杂的数据建模问题寻找和实现可处理的解决方案.g., 用户行为预测, recommender systems, NLP, spam filters, deduplication, or feature engineering.

Show More

在同一个Python文件中保持缩进一致.

Python中的缩进级别非常重要, 混合制表符和空格并不明智, 也不是推荐的做法. To go even further, Python 3将直接拒绝解释混合文件, 而在Python 2中,制表符的解释就像使用 8-space tab stops. So while executing, 您可能不知道正在考虑的特定行在哪个缩进级别.

对于任何你认为有一天会被别人阅读或使用的代码, 为了避免混淆,你应该坚持 PEP-8,或者您的团队特定的编码风格. PEP-8强烈反对在同一文件中混合制表符和空格.

欲了解更多信息,请查看此 Q&A on StackExchange:

  1. 第一个缺点是,它很快就会变得一团糟

格式化应该是IDE的任务. 开发人员已经做了足够多的工作来关心标签的大小, IDE将插入多少空间, etc. 代码的格式应该正确, 在其他配置下也能正确显示, 无需强迫开发者去思考.

Also, remember this:

Furthermore, 完全避免使用标签是个好主意, 因为在计算机世界中,制表符的语义并没有很好的定义, 它们可以在不同类型的系统和编辑器上以完全不同的方式显示. Also, 在复制-粘贴操作期间,选项卡经常被破坏或错误转换, 或者将一段源代码插入到网页或其他类型的标记代码中.

Contributors

Khaled Monsoor

后端工程师(自由职业者)

python软件开发人员. Big-data enthusiast. 摄影和咖啡爱好者.

学习使用Python字典

Dictionary data structure in Python is a way to store data; moreover, it is powerful and easy to use. 字典在其他语言中被称为“联想记忆”或“关联数组”。. 在Python中,字典是一个无序的集合 key: value 对,要求每个键都是唯一的.

在日常发展中,我们应该如何使用字典?

让我们用附带的代码示例来检查一些常见的用例. Let’s say you use many if/else clauses in your code:

if name == "John": 
   这是约翰,他是一位艺术家。
elif name == "Ted":
   打印"这是Ted,他是工程师"
elif name == "Kennedy":
   印刷"这是肯尼迪,他是个老师"

通过使用字典,我们可以像这样编写相同的代码:

name_job_dict = {
   “Josh”:“这是John,他是一个艺术家。”
   “泰德”:“这是泰德,他是一名工程师”,   
   " Kennedy ": "This is Kennedy, he is a teacher";
}
打印name_job_dict[名称]

第二个用例是当我们需要一个键的默认值时:

def count_duplicates(数字):
   result = {}
   for number in numbers:
       如果number不在result中:#这里不需要if
           result[key] = 0
       result[number] += 1
   return result

By using setdefault, we get cleaner code:

>>> def count_duplicates(数字):
   result = {}
   for number in numbers:
       result.Setdefault (number, 0) #这样更清楚
       result[number] += 1
   return result

我们也可以使用字典来操作列表:

>>> characters = {'a': 1, 'b': 2}
>>> characters.Items() //返回一个字典的(键,值)对列表的副本(http://docs.python.org/2/library/stdtypes.html#dict.items)
[('a', 1), ('b', 2)]
>>> characters = [['a', 1], ['b', 2], ['c', 3]]
>>> dict(characters) // return a new dictionary initialized from a list (http://docs.python.org/2/library/stdtypes.html#dict)
{'a': 1, 'b': 2, 'c': 3}

如果有必要,可以很容易地通过切换键和值来改变字典的形式 {key: value} to a new dictionary {value: key} -也被称为颠倒字典:

>>> characters = {'a': 1, 'b': 2, 'c': 3}
>>> invert_characters = {v: k for k, v in characters.iteritems()}
>>> invert_characters
{1: 'a', 2: 'b', 3: 'c'}

最后一个技巧与异常有关. 开发人员应该注意异常. 其中最烦人的是 KeyError exception. 要处理这个问题,开发人员必须首先检查一个键是否存在于字典中.

>>> character_occurrences = {'a': [], ‘b’: []}
>>> character_occurrences[‘c’]
KeyError: 'c'
>>> if ‘c’ not in character_occurrences:
        Character_occurrences [' c '] = []
>>> character_occurrences[‘c’]
[]
>>> try:
        打印character_occurrences (' d ')
    except: 
        打印"字符串中没有字符' d ' "

However, 实现干净和易于测试的代码, 必须避免异常捕获和条件. 这样就更容易理解了 defaultdict,在集合中使用.

>>> from collections import defaultdict
>>> character_occurrences = defaultdict(list)
>>> character_occurrences['a']
[]
>>> character_occurrences[‘b’].append(10)
>>> character_occurrences[‘b’].append(11)
>>> character_occurrences[‘b’]
[10, 11]

Contributors

Vu Quang Hoa

自由Python开发人员

Vietnam

Hoa,绰号乔,是一位才华横溢的工程师,能够很快掌握新概念. 他最引人注目的品质是无论做什么,他都表现出全身心的投入. 他擅长全栈, 高度可伸缩的Python-Django应用, 有Java和PHP经验. 他在StoryTree公司(美国500强初创公司之一)有超过两年的Django框架应用开发经验.

Show More

Submit a tip

提交的问题和答案将被审查和编辑, 并可能会或可能不会选择张贴, 由Toptal全权决定, LLC.

*所有字段均为必填项

Toptal Connects the Top 3% 世界各地的自由职业人才.

加入Toptal社区.