本文共 20359 字,大约阅读时间需要 67 分钟。
python 2 不再维护
For the first year or two when I started coding, I thought learning a language was all about learning the syntax. So, that’s all I did.
在开始编码的第一两年中,我认为学习语言就是学习语法。 所以,这就是我所做的。
Needless to say, I didn’t turn into a great developer. I was stuck. Then, one fine day, it just clicked. I realised I was doing this wrong. Learning the syntax should be the least of my concerns. What matters is everything else about the language. What exactly is all that? Read on.
不用说,我并没有成为一名出色的开发人员。 我卡住了。 然后,一天晴朗,它只是单击了。 我意识到自己做错了。 学习语法应该是我最不关心的事情。 重要的是关于语言的其他一切。 这到底是什么? 继续阅读。
This article is divided into three main subparts: The Data Model, the Execution model and the Lexical analysis.
本文分为三个主要子部分:数据模型,执行模型和词法分析。
This article is more an insight into how things work in Pythonland — in contrast to how to learn Python. You’ll find many how-to learning sources online.
本文更深入地了解了Pythonland中的工作原理-与如何学习Python形成了对比。 您会在网上找到许多how-to学习方法。
What I didn’t find online was a single source of common ‘gotchas’ in Python. A source explaining how the language works. This attempts to solve that problem. I think I’ve come up short, there’s so much to it!
我在网上找不到的是Python中常见的“陷阱”的单一来源。 解释该语言如何工作的来源。 这试图解决该问题。 我想我做的很短,有很多事情要做!
Everything here comes from the official documentation. I’ve condensed it — to the important points, reordered stuff and added my examples. All links point to the documentation.
这里的一切都来自官方文档。 我已经精简了这一点-重点,重新排列了内容并添加了示例。 所有链接都指向文档。
Without further ado, here we go.
事不宜迟,我们开始。
are Python’s abstraction for data.
是Python对数据的抽象。
Every object has its unique fixed identity
, a fixed type
and a value
.
每个对象都有其唯一的固定identity
,固定type
和value
。
‘Fixed’ means the identity
and type
of an Object
can never change.
“固定”表示Object
的identity
和type
永远不会改变。
The value
may change. Objects whose value can change are called mutable while objects whose value can’t change are called immutable.
该value
可能会更改。 值可以更改的对象称为可变对象,而值不能更改的对象称为不可变对象 。
The mutability is determined by type
:
可变性取决于type
:
The identity of objects can be compared via the is
operator.
可以通过is
运算符比较对象的身份。
id()
returns the identity
id()
返回identity
type()
returns the type
type()
返回type
Note: The value of an immutable container object that contains a reference to a mutable object can change when the latter’s value is changed. However, the container is still considered immutable, because the collection of objects it contains cannot be changed. So, immutability is not strictly the same as having an unchangeable value.
注意:当可变对象的值更改时,包含可变对象的引用的不可变容器对象的值可以更改。 但是,仍然认为容器是不可变的,因为它包含的对象的集合无法更改。 因此,不变性与具有不变值并不严格相同。
This note made my head spin the first two times I read it.
读此笔记的前两次,它使我的头旋转。
Simple translation: Immutability is not the same as unchangeable value. In the example below, the tuple
is immutable
, while it’s value
keeps changing (as the list
changes).
简单的翻译:不变性与不变的价值并不相同。 在下面的示例中, tuple
是immutable
,而其value
不断变化(随着list
变化)。
Example:
例:
>>> t = ("a", [1]) # a tuple of string and list>>> id(t)4372661064>>> t('a', [1])>>> type(t)>>> t[1][1]>>> t[1].append(2)>>> t('a', [1, 2])>>> id(t)4372661064>>> type(t)
The tuple is immutable, even though it contains a mutable object, a list.
元组是不可变的,即使它包含一个可变对象(一个列表)也是如此。
Compare this to a string, where changing the existing array changes the object (since strings are immutable).
将此与字符串进行比较,更改现有数组会更改对象(因为字符串是不可变的)。
>>> x = "abc">>> id(x)4371437472>>> x += "d">>> x'abcd'>>> id(x)4373053712
Here, the name , x
is bound to another object of type string. This changes its id as well.
在这里,名称x
被绑定到另一个字符串类型的对象。 这也会更改其ID。
The original object, being immutable, stays immutable. The binding is explained in further detail below, which should make things clearer.
不变的原始对象保持不变。 绑定将在下面更详细地说明,这应该使事情更清楚。
Python comes with several :
Python带有几种 :
The type is represented by a single object, hence a single value. The sole object with type = NoneType
该类型由单个对象表示,因此由单个值表示。 type = NoneType
的唯一对象
>>> type(None)
This is a collection of abstract base classes used to represent numbers. They can’t be instantiated, and int
, float
inherit from numbers.Number
.
这是用于表示数字的抽象基类的集合。 它们无法实例化,并且 int
, float
从numbers.Number
继承。
They are created by numeric literals and arithmetic operations. The returned objects are immutable, as we have seen. The following list of examples will make this clear:
它们是由数字文字和算术运算创建的。 如我们所见,返回的对象是不可变的。 以下示例列表将使这一点变得清楚:
>>> a = 3 + 4>>> type(a)>>> isinstance(a, numbers.Number)True>>> isinstance(a, numbers.Integral)True>>> isinstance(3.14 + 2j, numbers.Real)False>>> isinstance(3.14 + 2j, numbers.Complex)True
These represent finite ordered sets indexed by non negative integers. Just like an array from other languages.
这些代表由非负整数索引的有限有序集。 就像其他语言的数组一样。
len()
returns the length of sequences. When length is n
, the index set has elements from 0...n-1
. Then the ith element is selected by seq[i-1]
.
len()
返回序列的长度。 当length为n
,索引集的元素从0...n-1
。 然后通过seq[i-1]
选择第ith个元素。
For a sequence l
, you can select elements in between indexes using slicing: l[i:j]
.
对于序列l
,可以使用切片: l[i:j]
在索引之间选择元素。
There are two types of sequences: mutable and immutable.
序列有两种类型:可变序列和不可变序列。
These represent unordered, finite sets of unique, immutable objects. They can’t be indexed, but can be iterated over. len()
still returns the number of items in the set.
这些代表无序,有限的唯一不变对象集。 它们不能被索引,但是可以被迭代。 len()
仍返回集合中的项目数。
There are two types of sets: mutable and immutable.
集合有两种类型:可变的和不可变的。
A mutable set is created by set()
.
可变集合由set()
创建。
An immutable set is created by frozenset()
.
一个不可变的集合是由frozenset()
创建的。
These represent finite sets of objects indexed by nearly arbitrary values. Keys can’t be mutable objects. That includes lists, other dictionaries and other objects that are compared by value, and not by object identity.
这些代表由几乎任意值索引的有限对象集。 键不能是可变对象。 这包括按值而不是按对象标识比较的列表,其他字典和其他对象。
This means a frozenset
can be a dictionary key too!
这意味着frozenset
也可以是字典键!
A module object is a basic organisational unit in Python. The namespace is implemented as a dictionary. Attribute references are lookups in this dictionary.
模块对象是Python中的基本组织单位。 命名空间被实现为字典。 属性引用是此词典中的查找。
For a module m
, the dictionary is read-only, accessed by m.__dict__
.
对于模块m
,该词典是只读的,可以由m.__dict__
访问。
It’s a regular dictionary so you can add keys to it!
这是一本常规词典,因此您可以为其添加键!
Here’s an example, with the :
这是一个使用示例:
We are adding our custom function, figure()
to the module this
.
我们将自定义函数figure()
到模块this
。
>>> import this as t>>> t.__dict__{'__name__': 'this', '__doc__': None, '__package__': '',..........'s': "Gur Mra bs Clguba, ol Gvz Crgref\n\nOrnhgvshy vf orggre gunavqrn.\nAnzrfcnprf ner bar ubaxvat terng vqrn -- yrg'f qb zber bs gubfr!",'d': {'A': 'N', 'B': 'O', 'C': 'P', 'D': 'Q', 'E': 'R', 'F': 'S', 'u': 'h', 'v': 'i', 'w': 'j', 'x': 'k', 'y': 'l', 'z': 'm'},'c': 97,'i': 25}>>> def figure():... print("Can you figure out the Zen of Python?")... >>> t.fig = figure>>> t.fig()Can you figure out the Zen of Python?>>> t.__dict__{'__name__': 'this', '__doc__': None, '__package__': '',..........'s': "Gur Mra bs Clguba, ol Gvz Crgref\n\nOrnhgvshy vf orggre gunavqrn.\nAnzrfcnprf ner bar ubaxvat terng vqrn -- yrg'f qb zber bs gubfr!",'d': {'A': 'N', 'B': 'O', 'C': 'P', 'D': 'Q', 'E': 'R', 'F': 'S', 'u': 'h', 'v': 'i', 'w': 'j', 'x': 'k', 'y': 'l', 'z': 'm'},'c': 97,'i': 25'fig':}>>> print("".join([t.d.get(c, c) for c in t.s]))The Zen of Python, by Tim PetersBeautiful is better than ugly.Explicit is better than implicit.Simple is better than complex.Complex is better than complicated.Flat is better than nested.Sparse is better than dense.Readability counts.Special cases aren't special enough to break the rules.Although practicality beats purity.Errors should never pass silently.Unless explicitly silenced.In the face of ambiguity, refuse the temptation to guess.There should be one-- and preferably only one --obvious way to do it.Although that way may not be obvious at first unless you're Dutch.Now is better than never.Although never is often better than *right* now.If the implementation is hard to explain, it's a bad idea.If the implementation is easy to explain, it may be a good idea.Namespaces are one honking great idea -- let's do more of those!
Not very useful either, but good to know.
也不是很有用,但很高兴知道。
Python allows for .
Python允许 。
Classes have special function names — methods they can implement to use Python’s defined operators. This includes slicing, arithmetic operations and subscripting.
类具有特殊的函数名称-它们可以实现使用Python定义的运算符的方法。 这包括切片,算术运算和下标。
For example, __getitem__()
refers to subscripting. Hence, x[i]
is equivalent to type(x).__getitem__(x,i)
.
例如, __getitem__()
表示下标。 因此, x[i]
等效于type(x).__getitem__(x,i)
。
Hence, to use the operator []
on a class someClass
: you need to define __getitem__()
in someClass
.
因此,要在someClass
类上使用运算符[]
:您需要在someClass
定义__getitem__()
。
>>> class operatorTest(object):... vals = [1,2,3,4]... def __getitem__(self, i):... return self.vals[i]... >>> x = operatorTest()>>> x[2]3>>> x.__getitem__(2)3>>> type(x)>>> type(x).__getitem__(x,2)3>>> OperatorTest.__getitem__(x,2)3
Confused about why all of them are equivalent? That’s for next part — where we cover class and function definitions.
为何对它们全部等同感到困惑? 这是下一部分的内容-我们将介绍类和函数的定义。
Likewise, the __str__()
determines the output when the str()
method is called on an object of your class.
同样,当在类的对象上调用str()
方法时, __str__()
str()
__str__()
确定输出。
For comparison operations, the special function names are:
对于比较操作,特殊功能名称为:
object.__lt__(self, other)
for &
lt; (“less than”)
object.__lt__(self, other)
用于&
lt; (“少于”)
object.__le__(self, other)
for &l
t;= (“less than or equal to”)
object.__le__(self, other)
为&l
t; =(“小于或等于”)
object.__eq__(self, other)
for ==
(“equal to”)
object.__eq__(self, other)
for ==
(“等于”)
object.__ne__(self, other)
for !=
(“not equal to”)
object.__ne__(self, other)
为!=
(“不等于”)
object.__gt__(self, other)
for &
gt; (“greater than”)
object.__gt__(self, other)
为&
GT; (“比...更棒”)
object.__ge__(self, other)
for &g
t;= (“greater than or equal to”)
object.__ge__(self, other)
为&g
t; =(“大于或等于”)
So for example, x&l
t;y is called as x.__lt__
(y)
因此,例如, x&l
t; y称为as x.__lt__
(y)
There are also , like object.__add__(self, other)
.
还有一些 ,例如object.__add__(self, other)
。
As an example, x+y
is called as x.__add__(y)
例如, x+y
称为x.__add__(y)
Another interesting is __iter__()
.
另一个有趣的是__iter__()
。
You call this method when you need an iterator for a container. It returns a that can iterate over all the objects in the container.
当您需要容器的迭代器时,可以调用此方法。 它返回一个 ,该对象可以遍历容器中的所有对象。
For mappings, it should iterate over the keys of the container.
对于映射,它应该遍历容器的键。
The iterator object itself supports two methods:
迭代器对象本身支持两种方法:
iterator.__iter__()
: Returns the object itself.
iterator.__iter__()
:返回对象本身。
This makes iterators
and the containers
equivalent.
这使得iterators
和containers
等效。
This allows the iterator and containers both to be used in for
and in
statements.
这样就可以在for
和in
语句中使用迭代器和容器。
iterator.__next__()
: Returns the next item from the container. If there are no further items, raises the StopIteration
exception.
iterator.__next__()
:返回容器中的下一项。 如果没有其他项目,则引发StopIteration
异常。
class IterableObject(object): # The iterator object class vals = [] it = 0 def __init__(self, val): self.vals = val it = 0 def __iter__(self): return self def __next__(self): if self.it < len(self.vals): index = self.it self.it += 1 return self.vals[index] raise StopIteration class IterableClass(object): # The container class vals = [1,2,3,4] def __iter__(self): return iterableObject(self.vals)>>> iter_object_example = IterableObject([1,2,3])>>> for val in iter_object_example:... print(val)... 123>>> iter_container_example = IterableClass()>>> for val in iter_container_example:... print(val)... 1234
Cool stuff, right? There’s also a direct equivalent in Javascript.
很酷的东西,对不对? 在Javascript中也有直接等效项。
are also implemented via operator overloading.
器还通过运算符重载来实现。
with open(filename, 'r') as f
with open(filename, 'r') as f
open(filename, 'r')
is a context manager object which implements
open(filename, 'r')
是一个上下文管理器对象,它实现
object.__enter__(self)
and
object.__enter__(self)
和
object.__exit__(self, exc_type, exc_value, traceback)
All the above three parameters are null when error is None
.
object.__exit__(self, exc_type, exc_value, traceback)
当error为None
时,以上三个参数均为空。
class MyContextManager(object): def __init__(self, some_stuff): self.object_to_manage = some_stuff def __enter__(self): print("Entering context management") return self.object_to_manage # can do some transforms too def __exit__(self, exc_type, exc_value, traceback): if exc_type is None: print("Successfully exited") # Other stuff to close>>> with MyContextManager("file") as f:... print(f)... Entering context managementfileSuccessfully exited
This isn’t useful — but gets the point across. Does that make it useful anyway?
这没有用,但可以说明要点。 无论如何,这有用吗?
A block is a piece of code executed as a unit in an execution frame.
块是在执行框架中作为一个单元执行的一段代码。
Examples of blocks include:
块的示例包括:
But NOT for
loops and other control structures
但不适for
循环和其他控制结构
Remember how everything is an object
in Python?
还记得Python中的一切都是object
吗?
Well, you have names
bound to these objects
. These names
are what you think of as variables.
好了,您有绑定到这些objects
names
。 这些names
就是您认为的变量。
>>> xTraceback (most recent call last): File "", line 1, in NameError: name 'x' is not defined
Name binding, or assignment occurs in a block.
名称绑定或分配发生在块中。
Examples of name binding — these are intuitive:
名称绑定的示例-这些很直观:
Context managers: with ... as f
: f is the name binding to the ...
object
上下文管理器: with ... as f
:f是绑定到...
对象的名称
Names bound to a block are local to that block . That means global variables are simply names bound to the module.
绑定到块的名称是该块的本地名称。 这意味着全局变量只是绑定到模块的名称。
Variables used in a block without being defined there are free variables.
没有定义的块中使用的变量是自由变量。
Scopes define visibility of a name in a block. The scope of a variable includes the block it is defined in, as well as all blocks contained inside the defining block.
范围定义了块中名称的可见性。 变量的范围包括其定义所在的块以及定义块内包含的所有块。
Remember how for loops aren’t blocks? That’s why iteration variables defined in the loop are accessible after the loop, unlike in C++ and JavaScript.
还记得for循环不是块吗? 这就是为什么在循环之后可以访问循环中定义的迭代变量的原因,这与C ++和JavaScript不同。
>>> for i in range(5):... x = 2*i... print(x, i)... 0 02 14 26 38 4>>> print(x, i) # outside the loop! x was defined inside.8 4
When a name is used in a block, it is resolved using the nearest enclosing scope.
在块中使用名称时,将使用最近的封闭范围来解析它。
Note: If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block. This can lead to errors when a name is used within a block before it is bound.
注意:如果名称绑定操作发生在代码块内的任何位置,则该块内对该名称的所有使用均被视为对当前块的引用。 在绑定名称之前在块中使用名称时,这可能导致错误。
For example:
例如:
>>> name = "outer_scope">>> def foo():... name = "inner_function" if name == "outer_scope" \ else "not_inner_function"... >>> foo()Traceback (most recent call last): File "", line 1, in File " ", line 2, in fooUnboundLocalError: local variable 'name' referenced before assignment
This is a wonderful traceback, which should make sense now.
这是一个很棒的追溯,现在应该有意义。
We have the top level block, the module — in which there’s another block, the function. Every binding inside the function has the function as its top level scope!
我们有顶层模块,即模块-其中还有另一个模块,即功能。 函数内部的每个绑定都具有该函数的顶级作用域!
Hence, when you’re binding the name name
to the object "inner_function"
: before the binding you’re checking its value. The rule says you can’t reference it before the binding. Exactly the reason for the UnboundLocalError
.
因此,当你绑定的名字name
的对象"inner_function"
:之前绑定你检查它的价值。 规则说您不能在绑定之前引用它。 正是UnboundLocalError
的原因。
Python lets you use . To explicitly continue lines, use a backslash.
Python使您可以使用 。 要明确地继续行,请使用反斜杠。
Comments aren’t allowed after line joinings.
连线加入后不允许发表评论。
if a < 10 and b < 10 \ # Comment results in SyntaxErrorand c < 10: # Comment okay return Trueelse: return False
Implicitly, line joining occurs on its own when elements are inside braces. Comments here are allowed.
隐式地,当元素在花括号内时,线连接会自行发生。 允许在这里发表评论。
month_names = ['Januari', 'Februari', 'Maart', # These are the 'April', 'Mei', 'Juni', # Dutch names 'Juli', 'Augustus', 'September', # for the months 'Oktober', 'November', 'December'] # of the year
The number of spaces / tabs in the doesn’t matter, as long as it’s increasing for things that should be indented. The first line shouldn’t be indented.
中的空格/制表符的数量无关紧要,只要对于应缩进的事物而言,空格/制表符的数量不断增加。 第一行不应缩进。
The four spaces rule is a convention defined by . It’s good practice to follow it.
四个空格规则是定义的约定。 遵循它是一个好习惯。
# Compute the list of all permutations of l.def perm(l): # Comment indentation is ignored if len(l) <= 1: return [l] r = [] for i in range(len(l)): s = l[:i] + l[i+1:] # Indentation level chosen p = perm(s) # Must be same level as above for x in p: r.append(l[i:i+1] + x) # One space okay return r
There are a few reserved identifiers as well.
也有一些保留的标识符。
_
for import: functions / variables starting with _
aren’t imported.
_
表示导入:不会导入以_
开头的函数/变量。
__*__
for system defined names, defined by implementation : we’ve seen a few of these. ( __str__()
, __iter__()
, __add__()
)
__*__
用于系统定义的名称,由实现定义:我们已经看到了其中一些。 ( __str__()
, __iter__()
, __add__()
)
Python also offers
Python还提供了
>>> def name():... return "Neil" "Kakkar"...>>> name()'Neil Kakkar'
is a useful tool in Python.
是Python中有用的工具。
Strings can have { expr }
in the string literal where expr
is an expression. The expression evaluation is substituted in place.
字符串的字符串文字中可以包含{ expr }
,其中expr
是一个表达式。 表达式评估将被替换。
Conversions can be specified to convert the result before formatting.
可以指定转换以在格式化之前转换结果。
!r
calls repr()
, !s
calls str()
and !a
calls ascii()
!r
调用repr()
!s
调用str()
和!a
调用ascii()
>>> name = "Fred">>> f"He said his name is {name!r}.""He said his name is 'Fred'.">>> f"He said his name is {repr(name)}." # repr() is equiv. to !r"He said his name is 'Fred'.">>> width = 10>>> precision = 4>>> value = decimal.Decimal("12.34567")>>> f"result: {value:{width}.{precision}}" # nested fields'result: 12.35'# This is same as "{decf:10.4f}".format(decf=float(value))>>> today = datetime(year=2017, month=1, day=27)>>> f"{today:%B %d, %Y}" # using date format specifier'January 27, 2017'>>> number = 1024>>> f"{number:#0x}" # using integer format specifier'0x400'
It’s a cleaner syntax to using
使用是一种更
语法
With this, we’ve covered the major pillars of Python. The object data model, execution model with its scopes and blocks and some bits on strings. Knowing all this puts you ahead of every developer who only knows the syntax. That’s a higher number than you think.
这样,我们就涵盖了Python的主要Struts。 对象数据模型,执行模型及其作用域和块以及字符串上的一些位。 了解所有这些,使您领先于仅知道语法的每个开发人员。 这个数字比您想象的要高。
In Part 2, we’ll look at object based classes and functions.
在第2部分中,我们将研究基于对象的类和函数。
To learn more, here’s a great book — .[Affiliate link — thanks for supporting!]
要了解更多信息,这是一本很棒的书- 。[会员链接-感谢您的支持!]
Other stories in this series:
本系列中的其他故事:
Enjoyed this?
喜欢这个吗?
翻译自:
python 2 不再维护
转载地址:http://wfwzd.baihongyu.com/