-
Notifications
You must be signed in to change notification settings - Fork 1
/
atom.xml
115 lines (71 loc) · 75.6 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Jamie's Blog</title>
<subtitle>Talk is cheap, show me the code.</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://yoursite.com/"/>
<updated>2018-04-28T02:24:35.920Z</updated>
<id>http://yoursite.com/</id>
<author>
<name>Jamie</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>Mutable and Immutable</title>
<link href="http://yoursite.com/2018/04/27/mutable_immutable/"/>
<id>http://yoursite.com/2018/04/27/mutable_immutable/</id>
<published>2018-04-26T16:00:00.000Z</published>
<updated>2018-04-28T02:24:35.920Z</updated>
<content type="html"><![CDATA[<p>immutable指对象一经创建,即不可修改。对象是不是immutable取决于数据类型,比如</p><p>整型(integer)、字符串(string)和元组(tuple)都是immutable,</p><p>而列表(list)、字典(dictionary)、集合(set)都是mutable。</p><a id="more"></a><h3 id="不可变的元祖-tuple-immutable"><a href="#不可变的元祖-tuple-immutable" class="headerlink" title="不可变的元祖 tuple (immutable)"></a>不可变的元祖 tuple (immutable)</h3><p>tuple和list非常类似,但是tuple一旦初始化就不能修改</p><p>tuple不能变了,它也没有append(),insert()这样的方法。其他获取元素的方法和list是一样的,你可以正常地使用索引,但不能赋值成另外的元素。</p><p>不可变的tuple有什么意义?因为tuple不可变,所以代码更安全。如果可能,能用tuple代替list就尽量用tuple。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">t = (<span class="number">1</span>, <span class="number">2</span>) <span class="comment"># 当你定义一个tuple时,在定义的时候,tuple的元素就必须被确定下来</span></span><br><span class="line">print(t)</span><br><span class="line"></span><br><span class="line">p = () <span class="comment"># 定义一个空的tuple</span></span><br><span class="line">print(type(p))</span><br><span class="line"></span><br><span class="line">c = (<span class="number">1</span>) <span class="comment"># 要定义一个只有1个元素的tuple,如果你这么定义</span></span><br><span class="line">print(type(c)) </span><br><span class="line"><span class="string">'''</span></span><br><span class="line"><span class="string">定义的不是tuple,是1这个数!这是因为括号()既可以表示tuple,又可以表示数学公式中的小括号,</span></span><br><span class="line"><span class="string">这就产生了歧义,因此,Python规定,这种情况下,按小括号进行计算,计算结果自然是1。</span></span><br><span class="line"><span class="string">'''</span></span><br><span class="line"></span><br><span class="line">a = (<span class="number">1</span>,) <span class="comment">#所以只有1个元素的tuple定义时必须加一个逗号,,来消除歧义</span></span><br><span class="line">print(type(a))</span><br></pre></td></tr></table></figure><pre><code>(1, 2)<class 'tuple'><class 'int'><class 'tuple'></code></pre><h3 id="一个“可变的”tuple"><a href="#一个“可变的”tuple" class="headerlink" title="一个“可变的”tuple"></a>一个“可变的”tuple</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">t = (<span class="string">'a'</span>, <span class="string">'b'</span>, [<span class="string">'A'</span>, <span class="string">'B'</span>])</span><br><span class="line">print(<span class="string">'before change, this tuple is'</span>.format(t))</span><br><span class="line">t[<span class="number">2</span>][<span class="number">0</span>] = <span class="string">'X'</span></span><br><span class="line">t[<span class="number">2</span>][<span class="number">1</span>] = <span class="string">'Y'</span></span><br><span class="line">print(<span class="string">'after change,this tuple is'</span>.format(t))</span><br></pre></td></tr></table></figure><pre><code>before change, this tuple isafter change,this tuple is</code></pre><p>这个tuple定义的时候有3个元素,分别是’a’,’b’和一个list。不是说tuple一旦定义后就不可变了吗?怎么后来又变了?</p><p>表面上看,tuple的元素确实变了,但其实变的不是tuple的元素,而是list的元素。tuple一开始指向的list并没有改成别的list,所以,tuple所谓的“不变”是说,tuple的每个元素,指向永远不变。即指向’a’,就不能改成指向’b’,指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的!</p><p>理解了“指向不变”后,要创建一个内容也不变的tuple怎么做?那就必须保证tuple的每一个元素本身也不能变,就是immutable对象。</p><h3 id="可哈希-hashable"><a href="#可哈希-hashable" class="headerlink" title="可哈希 hashable"></a>可哈希 hashable</h3><p>哈希表是在一个关键字和一个较大的数据之间建立映射的表,能使对一个数据序列的访问过程更加迅速有效。用作查询的关键字必须唯一且固定不变,于是只有immutable的对象才可以作为关键字,也叫hashable.<br>如上所述,整型(integer)、字符串(string)和元组(tuple)都可以作为关键字,而list不可以。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">d = {<span class="number">1</span>:<span class="number">2</span>, <span class="string">'Ben'</span>:<span class="number">123</span>, (<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>):<span class="number">456</span>}</span><br><span class="line">c = {<span class="number">1</span>:<span class="number">2</span>, <span class="string">'Ben'</span>:<span class="number">123</span>, [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]:<span class="number">456</span>} <span class="comment"># 报错,因为用做字典键的是可变的list</span></span><br></pre></td></tr></table></figure><pre><code>---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-9-9b59cc95aefa> in <module>() 1 d = {1:2, 'Ben':123, (1,2,3):456}----> 2 c = {1:2, 'Ben':123, [1,2,3]:456} # 报错,因为用做字典键的是可变的listTypeError: unhashable type: 'list'</code></pre><h3 id="可变与不可变的特性"><a href="#可变与不可变的特性" class="headerlink" title="可变与不可变的特性"></a>可变与不可变的特性</h3><p>list列表是可变的,所以它的方法大多是就地修改,像 insert(),append(),extend(),sort(),reverse()然后没有返回,或者说返回值为None. pop()方法,它在末端删除一个元素,并可以将删除的元素作为返回值返回给调用者</p><p>tuple元祖是不可变的,所以它的方法大多无法就地修改,</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">L = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>]</span><br><span class="line">L = L.insert(<span class="number">6</span>,<span class="number">2</span>) </span><br><span class="line">print(L[<span class="number">2</span>])</span><br></pre></td></tr></table></figure><pre><code>---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-10-ad4d9f0257b3> in <module>() 1 L = [1,2,3,4,5] 2 L = L.insert(6,2)----> 3 print(L[2])TypeError: 'NoneType' object is not subscriptable</code></pre><p>这里犯了一个常见的错误,因为我们说过插入是就地修改,而不是返回修改后的新列表。Insert方法的返回值是None,然后你把None值赋给了L,这样就底失去之前列表的引用。</p><p>给tuple元祖排序</p><p>1.先将其转化为列表,本地排序后再转化回元组:</p><p>list.sort() 列表方法就地修改,无返回值</p><p>2.内置sorted函数:</p><p>sorted(可迭代对象)函数,返回一个已经排好序的list序列</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">T = (<span class="string">'cc'</span>,<span class="string">'bb'</span>,<span class="string">'dd'</span>,<span class="string">'aa'</span>)</span><br><span class="line">tmp = list(T)</span><br><span class="line">tmp.sort()</span><br><span class="line">T = tuple(tmp)</span><br><span class="line">print(T)</span><br><span class="line"></span><br><span class="line">C = (<span class="string">'cc'</span>,<span class="string">'bb'</span>,<span class="string">'dd'</span>,<span class="string">'aa'</span>)</span><br><span class="line">print(sorted(C))</span><br><span class="line"></span><br><span class="line">[<span class="string">'aa'</span>, <span class="string">'bb'</span>, <span class="string">'cc'</span>, <span class="string">'dd'</span>]</span><br></pre></td></tr></table></figure><pre><code>('aa', 'bb', 'cc', 'dd')['aa', 'bb', 'cc', 'dd']['aa', 'bb', 'cc', 'dd']</code></pre>]]></content>
<summary type="html">
<p>immutable指对象一经创建,即不可修改。对象是不是immutable取决于数据类型,比如</p>
<p>整型(integer)、字符串(string)和元组(tuple)都是immutable,</p>
<p>而列表(list)、字典(dictionary)、集合(set)都是mutable。</p>
</summary>
<category term="Topics" scheme="http://yoursite.com/categories/Topics/"/>
<category term="mutable" scheme="http://yoursite.com/tags/mutable/"/>
<category term="immutable" scheme="http://yoursite.com/tags/immutable/"/>
</entry>
<entry>
<title>Regex in Python</title>
<link href="http://yoursite.com/2018/04/27/regex/"/>
<id>http://yoursite.com/2018/04/27/regex/</id>
<published>2018-04-26T16:00:00.000Z</published>
<updated>2018-04-28T02:24:10.481Z</updated>
<content type="html"><![CDATA[<p>正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。</p><a id="more"></a><h2 id="字符"><a href="#字符" class="headerlink" title="字符"></a>字符</h2><p>. 字符在正则表达式代表着可以代表任何一个字符(包括它本身)</p><p>\d 可以匹配一个数字 等同于[0-9]</p><p>\D 等同于[^0-9]匹配非数字</p><p>\w 等同于[a-z0-9A-Z_]匹配大小写字母、数字和下划线</p><p>\W 等同于[^a-z0-9A-Z_]等同于上一条取非</p><p>A|B 可以匹配A或B,所以(P|p)ython可以匹配’Python’或者’python’</p><p>^ 表示行的开头,^\d表示必须以数字开头</p><p>\$ 表示行的结束,\d$表示必须以数字结束</p><p>\s 可以匹配空白字符,等价于 [\t\n\r\f]。(也包括Tab等空白符)</p><p>\S 匹配任意非空字符 </p><h2 id="量词"><a href="#量词" class="headerlink" title="量词"></a>量词</h2><p>跟着一个字符或一个表达式后面,表示前面重复的次数</p><p>+ 匹配前面的字符1次或多次(>=1)</p><p>* 匹配前面的字符0次或多次(>=0)</p><p>? 匹配前面的字符1次或者多次 (0 or 1)</p><p>{m} 匹配前面表达式m次 (=m)</p><p>{m,} 匹配前面表达式至少m次 (>=m)</p><p>{,n} 匹配前面的正则表达式最多n次 (<=m)</p><p>{m,n} 匹配前面的正则表达式m到n次 (>m,<n)</p><p>注意点:<br>以上量词都是贪婪模式,会尽可能多的匹配,如果要改为非贪婪模式,通过在量词后面跟随一个?来实现</p><h2 id="贪婪匹配"><a href="#贪婪匹配" class="headerlink" title="贪婪匹配"></a>贪婪匹配</h2><p>因为正则表达式默认是“贪婪”的,贪婪匹配,也就是匹配尽可能多的字符。</p><p>“+”代表是字符重复一次或多次。但是这个多次到底是多少次。所以它会尽可能“贪婪”地多给我们匹配字符,在这个例子里也就是匹配到最后一个“.”。我们怎么解决这种问题呢?只要在“+”后面加一个“?”就好了。</p><p>例子:理想的结果是@hit.结果是@hit.edu.</p><p>当需要用到 ‘+’ 或 ‘*’ 这种一定先想好到底是用贪婪型还是懒惰型</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> re</span><br><span class="line"></span><br><span class="line">key = <span class="string">r"[email protected]"</span></span><br><span class="line">p1 = <span class="string">r"@.+\."</span><span class="comment">#我想匹配到@后面一直到“.”之间的,在这里是hit</span></span><br><span class="line"><span class="comment">#p1 = r'@[a-z]{3}\.'</span></span><br><span class="line">pattern1 = re.compile(p1)</span><br><span class="line"><span class="keyword">print</span> (pattern1.findall(key))</span><br></pre></td></tr></table></figure><pre><code>['@hit.edu.']</code></pre><h2 id="范围"><a href="#范围" class="headerlink" title="范围"></a>范围</h2><p>[] 代表匹配里面的字符中的任意一个</p><p>[^] 代表除了内部包含的字符以外都能匹配,[^abc] 匹配除了a,b,c之外的字符</p><p>[0-9] 0123456789任意之一</p><p>[a-z] 小写字母任意之一</p><p>[A-Z] 大写字母任意之一</p><p>[0-9a-zA-Z_] 可以匹配一个数字、字母或者下划线;</p><p>[0-9a-zA-Z_]+ 可以匹配至少由一个数字、字母或者下划线组成的字符串,比如’a100’,’0_Z’,’Py3000’等等;</p><p>[a-zA-Z_][0-9a-zA-Z_]* 可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串,也就是Python合法的变量;</p><p>[a-zA-Z_][0-9a-zA-Z_]{0, 19} 更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。</p><h2 id="转义符"><a href="#转义符" class="headerlink" title="转义符"></a>转义符</h2><p>特殊字符:.^$?+*{}<a href=""></a>|<br>以上特殊字符要想使用字面值,必须使用\进行转义</p><h2 id="向前向后查找"><a href="#向前向后查找" class="headerlink" title="向前向后查找"></a>向前向后查找</h2><p>?<=后面跟着的是前缀要求,?=后面跟的是后缀要求。</p><p>exp1(?=exp2) 表示exp1后面的内容要匹配exp2(前瞻)</p><p>exp1(?!exp2) 表示exp1后面的内容不能匹配exp2 (负前瞻)</p><p>(?<=exp2)exp1 表示exp1前面的内容要匹配exp2 (后顾)</p><p>(?<!exp2)exp1 表示exp1前面的内容不能匹配exp2 (负后顾)</p><p>例如:我们要查找hello,但是hello后面必须是world,正则表达式可以这样写:”(hello)\s+(?=world)”,用来匹配”hello wangxing”和”hello world”只能匹配到后者的hello</p><p>(?<=exp1)exp(?=exp2) 表示exp前面的内容要匹配exp1,后面的内容要匹配exp2,即exp1expexp2</p><p>匹配到两个括号中间的</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> re</span><br><span class="line"></span><br><span class="line">key = <span class="string">r"<html><body><h1>hello world</h1></body></html>"</span><span class="comment">#这段是你要匹配的文本</span></span><br><span class="line">p1 = <span class="string">r"(?<=<h1>).+?(?=</h1>)"</span><span class="comment">#这是我们写的正则表达式规则</span></span><br><span class="line">pattern1 = re.compile(p1)<span class="comment">#我们在编译这段正则表达式</span></span><br><span class="line">matcher1 = re.search(pattern1,key)<span class="comment">#在源文本中搜索符合正则表达式的部分</span></span><br><span class="line">print(matcher1.group(<span class="number">0</span>))<span class="comment">#打印出来</span></span><br><span class="line"></span><br><span class="line">print(re.search(p1,key).group(<span class="number">0</span>))</span><br></pre></td></tr></table></figure><pre><code>hello worldhello world</code></pre><h2 id="回溯引用"><a href="#回溯引用" class="headerlink" title="回溯引用"></a>回溯引用</h2><p>原本要匹配<h1>\</h1>之间的内容,现在你知道HTML有多级标题,你想把每一级的标题内容都提取出来。你也许会这样写:</p><p>p = r”<h[1-6]>.*?</h[1-6]>” </p><p>这样一来,你就可以将HTML页面内所有的标题内容全部匹配出来。即<h1>\</h1>到<h6>\</h6>的内容都可以被提取出来。但是我们之前说过,写正则表达式困难的不是匹配到想要的内容,而是尽可能的不匹配到不想要的内容。在这个例子中,很有可能你就会被下面这样的用例玩坏。</p><p>比方说</p><p><h1>hello world</h3></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> re</span><br><span class="line"></span><br><span class="line">key = <span class="string">r"<h1>hello world</h3>"</span></span><br><span class="line">p1 = <span class="string">r"<h([1-6])>.*?</h\1>"</span></span><br><span class="line">pattern1 = re.compile(p1)</span><br><span class="line">m1 = re.search(pattern1,key)</span><br><span class="line">print(m1.group(<span class="number">0</span>))<span class="comment">#这里是会报错的,因为匹配不到,你如果将源字符串改成</h1></span></span><br><span class="line"><span class="comment">#结尾就能看出效果</span></span><br></pre></td></tr></table></figure><pre><code><h1>hello world</h1></code></pre><p>看到\1了吗?原本那个位置应该是[1-6],但是我们写的是\1,我们之前说过,转义符\干的活就是把特殊的字符转成一般的字符,把一般的字符转成特殊字符。普普通通的数字1被转移成什么了呢?在这里1表示第一个子表达式,也就是说,它是动态的,是随着前面第一个子表达式的匹配到的东西而变化的。比方说前面的子表达式内是[1-6],在实际字符串中找到了1,那么后面的\1就是1,如果前面的子表达式在实际字符串中找到了2,那么后面的\1就是2。</p><p>类似的,\2,\3,….就代表第二个第三个子表达式。</p><p>所以回溯引用是正则表达式内的一个“动态”的正则表达式,让你根据实际的情况变化进行匹配。</p><h2 id="re-match函数"><a href="#re-match函数" class="headerlink" title="re.match函数"></a>re.match函数</h2><p>re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。</p><p><span class="mark">re.match(pattern, string, flags=0)</span></p><p>pattern 匹配的正则表达式</p><p>string 要匹配的字符串</p><p>flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等</p><p>可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。</p><p>group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。</p><p>groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> re </span><br><span class="line"></span><br><span class="line">print(re.match(<span class="string">'www'</span>, <span class="string">'www.google.com'</span>)) <span class="comment"># 在起始位置匹配,成功</span></span><br><span class="line">print(re.match(<span class="string">'com'</span>, <span class="string">'www.google.com'</span>)) <span class="comment"># 不在起始位置匹配,失败</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#group 分组,从左到右</span></span><br><span class="line">print(re.match(<span class="string">'(.*\d)\.(.*\d)\.'</span>, <span class="string">'www1.google2.com3'</span>).group()) </span><br><span class="line">print(re.match(<span class="string">'(.*\d)\.(.*\d)\.'</span>, <span class="string">'www1.google2.com3'</span>).group(<span class="number">1</span>)) </span><br><span class="line">print(re.match(<span class="string">'(.*\d)\.(.*\d)\.'</span>, <span class="string">'www1.google2.com3'</span>).group(<span class="number">2</span>)) </span><br><span class="line"></span><br><span class="line"><span class="comment">#group 嵌套,从外到内,再从左到右</span></span><br><span class="line">print(re.match(<span class="string">'((.*\d)\.(.*\d))\.'</span>, <span class="string">'www1.google2.com3'</span>).group(<span class="number">1</span>)) <span class="comment"># group(1)是最外层</span></span><br><span class="line">print(re.match(<span class="string">'((.*\d)\.(.*\d))\.'</span>, <span class="string">'www1.google2.com3'</span>).group(<span class="number">2</span>)) <span class="comment"># group(2)内层从左向右</span></span><br><span class="line">print(re.match(<span class="string">'((.*\d)\.(.*\d))\.'</span>, <span class="string">'www1.google2.com3'</span>).group(<span class="number">3</span>)) <span class="comment"># group(3)内层从左向右</span></span><br></pre></td></tr></table></figure><pre><code><_sre.SRE_Match object; span=(0, 3), match='www'>Nonewww1.google2.www1google2www1.google2www1google2</code></pre><h2 id="re-search方法"><a href="#re-search方法" class="headerlink" title="re.search方法"></a>re.search方法</h2><p>re.search 扫描整个字符串并返回第一个成功的匹配。</p><p><span class="mark">re.search(pattern, string, flags=0)</span></p><p>pattern 匹配的正则表达式</p><p>string 要匹配的字符串</p><p>flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等</p><p>可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> re </span><br><span class="line"></span><br><span class="line">print(re.search(<span class="string">'www'</span>, <span class="string">'www.google.com'</span>)) <span class="comment"># 在起始位置匹配,成功</span></span><br><span class="line">print(re.search(<span class="string">'com'</span>, <span class="string">'www.google.com'</span>)) <span class="comment"># 不在起始位置匹配,成功</span></span><br></pre></td></tr></table></figure><pre><code><_sre.SRE_Match object; span=(0, 3), match='www'><_sre.SRE_Match object; span=(11, 14), match='com'></code></pre><h2 id="re-match与re-search的区别"><a href="#re-match与re-search的区别" class="headerlink" title="re.match与re.search的区别"></a>re.match与re.search的区别</h2><p>re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。</p><h2 id="检索和替换、删除"><a href="#检索和替换、删除" class="headerlink" title="检索和替换、删除"></a>检索和替换、删除</h2><p>re.sub用于替换字符串中的匹配项。</p><p><span class="mark">re.sub(pattern, repl, string, count=0)</span></p><p>pattern : 正则中的模式字符串。</p><p>repl : 替换的字符串,也可为一个函数。</p><p>string : 要被查找替换的原始字符串。</p><p>count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">phone = <span class="string">'2004-959-559 # 这是一个电话号码'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">#删除注释部分</span></span><br><span class="line">num = re.sub(<span class="string">'#.*'</span>,<span class="string">''</span>,phone)</span><br><span class="line">print(num)</span><br><span class="line"></span><br><span class="line"><span class="comment">#移除非数字的内容</span></span><br><span class="line">num = re.sub(<span class="string">'\D'</span>,<span class="string">''</span>,phone)</span><br><span class="line">print(num)</span><br></pre></td></tr></table></figure><pre><code>2004-959-559 2004959559</code></pre><h2 id="匹配汉字"><a href="#匹配汉字" class="headerlink" title="匹配汉字"></a>匹配汉字</h2><p>[\u4e00-\u9fa5] 至少匹配一个汉字</p><p>这两个unicode值正好是Unicode表中的汉字的头和尾。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> re</span><br><span class="line">print(re.match(<span class="string">'[\u4e00-\u9fa5]'</span>, <span class="string">'你好'</span>)) </span><br><span class="line">line = <span class="string">'study in 南京大学'</span></span><br><span class="line">print(re.match(<span class="string">'.*([\u4e00-\u9fa5]+大学)'</span>,line).group(<span class="number">1</span>)) <span class="comment">#贪婪匹配</span></span><br><span class="line">print(re.match(<span class="string">'.*?([\u4e00-\u9fa5]+大学)'</span>,line).group(<span class="number">1</span>)) <span class="comment">#非贪婪匹配</span></span><br></pre></td></tr></table></figure><pre><code><_sre.SRE_Match object; span=(0, 1), match='你'>京大学南京大学</code></pre><h2 id="小测试"><a href="#小测试" class="headerlink" title="小测试"></a>小测试</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> re</span><br><span class="line">m =[ <span class="string">'XXX出生于2011年6月1日'</span>,<span class="string">'XXX出生于2011年6月'</span>,<span class="string">'XXX出生于2011/6/1'</span>,<span class="string">'XXX出生于2011-6-1'</span>,<span class="string">'XXX出生于2011-06-01'</span>,<span class="string">'XXX出生于2011-06'</span>]</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> m:</span><br><span class="line"> print(re.match(<span class="string">'.*出生于(\d{4}[年/-]\d{1,2}([月/-]\d{1,2}.?|[月/-]$|$))'</span>,i).group(<span class="number">1</span>))</span><br></pre></td></tr></table></figure><pre><code>2011年6月1日2011年6月2011/6/12011-6-12011-06-012011-06</code></pre><h2 id="普遍邮箱适用的正则表达式"><a href="#普遍邮箱适用的正则表达式" class="headerlink" title="普遍邮箱适用的正则表达式"></a>普遍邮箱适用的正则表达式</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> re</span><br><span class="line">text = <span class="string">'[email protected] [email protected] [email protected]'</span></span><br><span class="line">reg = <span class="string">r'[A-Za-z0-9.]+@[A-Za-z0-9]+\.[a-z]{3}'</span></span><br><span class="line">print(re.findall(reg,text))</span><br></pre></td></tr></table></figure><pre><code>['[email protected]', '[email protected]', '[email protected]']</code></pre><h2 id="re-findall-与-re-search-的区别"><a href="#re-findall-与-re-search-的区别" class="headerlink" title="re.findall() 与 re.search() 的区别"></a>re.findall() 与 re.search() 的区别</h2><p>re.search匹配整个字符串,直到找到一个匹配,返回一个Match对象</p><p>和re.match一样<br>通过Match对象内的group编号或命名,获得对应的值</p><p>注意到group(0)永远是原始字符串,group(1)、group(2)……表示第1、2、……个子串</p><p>re.findall返回一个列表对象,包含所有匹配的字符串</p><p>正则表达式中没有使用分组,即没有括号,返回值是匹配到的完整字符串的列表</p><p>正则表达式中有使用分组,即有括号,返回值是各个group的值所组合出来的列表</p><p>所以要通过findall,想要获得整个字符串的话,就要使用不带括号的,即没有分组</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> re</span><br><span class="line">text = <span class="string">'[email protected] [email protected] [email protected]'</span></span><br><span class="line">reg = <span class="string">r'[A-Za-z0-9.]+@[A-Za-z0-9]+\.[a-z]{3}'</span></span><br><span class="line">print(re.search(reg,text))<span class="comment"># 返回第一个匹配的Match对象</span></span><br><span class="line">print(re.search(reg,text).group(<span class="number">0</span>))<span class="comment"># group(0)获取值</span></span><br><span class="line">print(re.findall(reg,text))</span><br><span class="line"></span><br><span class="line"><span class="comment">## 邮箱正则表达式</span></span><br><span class="line">reg2 = <span class="string">r'[A-Za-z0-9_]+@[a-zA-Z0-9]+\.(cn|com|ru|net|gmail)'</span></span><br><span class="line"></span><br><span class="line">email = re.search(reg,text) <span class="comment"># 匹配到第一个邮箱</span></span><br><span class="line">email2 = re.findall(reg2,text) <span class="comment"># 结果是['com', 'com', 'com'] 为什么?</span></span><br><span class="line">print(email.group(<span class="number">0</span>))</span><br><span class="line">print(email2) </span><br><span class="line"><span class="comment"># 在re.findall(),中的正则表达式有使用分组,即有括号,返回值是各个group的值所组合出来的列表</span></span><br></pre></td></tr></table></figure><pre><code><_sre.SRE_Match object; span=(0, 15), match='[email protected]'>[email protected]['[email protected]', '[email protected]', '[email protected]'][email protected]['com', 'com', 'com']</code></pre>]]></content>
<summary type="html">
<p>正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。</p>
</summary>
<category term="Topics" scheme="http://yoursite.com/categories/Topics/"/>
<category term="Regex" scheme="http://yoursite.com/tags/Regex/"/>
</entry>
<entry>
<title>Shallowcopy and Deepcopy</title>
<link href="http://yoursite.com/2018/04/27/shallowcopy_deepcopy/"/>
<id>http://yoursite.com/2018/04/27/shallowcopy_deepcopy/</id>
<published>2018-04-26T16:00:00.000Z</published>
<updated>2018-04-28T02:24:29.545Z</updated>
<content type="html"><![CDATA[<h2 id="赋值操作认识"><a href="#赋值操作认识" class="headerlink" title="赋值操作认识"></a>赋值操作认识</h2><p>1.赋值是将一个对象的地址赋值给一个变量,让变量指向该地址</p><p>2.修改不可变对象(str、tuple)需要开辟新的空间</p><p>3修改可变对象(list等)不需要开辟新的空间</p><a id="more"></a><h2 id="浅拷贝(-新瓶装旧酒-)"><a href="#浅拷贝(-新瓶装旧酒-)" class="headerlink" title="浅拷贝( 新瓶装旧酒 )"></a>浅拷贝( 新瓶装旧酒 )</h2><p>浅拷贝仅仅复制了容器中元素的地址</p><p>浅拷贝是在另一块地址中创建一个新的变量或容器,但是容器内的元素的地址均是源对象的元素的地址的拷贝。也就是说新的容器中指向了旧的元素( 新瓶装旧酒 )</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">a = [<span class="string">'hello'</span>,[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]]</span><br><span class="line">b = a[:] <span class="comment">#浅拷贝</span></span><br><span class="line">print(<span class="string">'源对象a--{}:{}'</span>.format(a,[id(x) <span class="keyword">for</span> x <span class="keyword">in</span> a]))</span><br><span class="line">print(<span class="string">'浅拷贝对象b--{}:{}'</span>.format(b,[id(x) <span class="keyword">for</span> x <span class="keyword">in</span> b]))</span><br><span class="line">print(<span class="string">'修改浅拷贝对象b'</span>)</span><br><span class="line">b[<span class="number">0</span>] = <span class="string">'world'</span></span><br><span class="line">b[<span class="number">1</span>].append(<span class="number">4</span>)</span><br><span class="line">print(<span class="string">'修改后源对象a--{}:{}'</span>.format(a,[id(x) <span class="keyword">for</span> x <span class="keyword">in</span> a]))</span><br><span class="line">print(<span class="string">'修改后浅拷贝对象b--{}:{}'</span>.format(b,[id(x) <span class="keyword">for</span> x <span class="keyword">in</span> b]))</span><br></pre></td></tr></table></figure><pre><code>源对象a--['hello', [1, 2, 3]]:[2924681864392, 2924682934600]浅拷贝对象b--['hello', [1, 2, 3]]:[2924681864392, 2924682934600]修改浅拷贝对象b修改后源对象a--['hello', [1, 2, 3, 4]]:[2924681864392, 2924682934600]修改后浅拷贝对象b--['world', [1, 2, 3, 4]]:[2924682621760, 2924682934600]</code></pre><p>改变前后,可变的list地址都是一样的<br>改变前后,不变的str地址有变化</p><h2 id="深拷贝(新瓶装新酒)"><a href="#深拷贝(新瓶装新酒)" class="headerlink" title="深拷贝(新瓶装新酒)"></a>深拷贝(新瓶装新酒)</h2><p>深拷贝,完全拷贝了一个副本,容器内部元素地址都不一样</p><p>深拷贝是在另一块地址中创建一个新的变量或容器,同时容器内的元素的地址也是新开辟的,仅仅是值相同而已,是完全的副本。也就是说( 新瓶装新酒 )。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> copy <span class="keyword">import</span> deepcopy</span><br><span class="line">a = [<span class="string">'hello'</span>,[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>]]</span><br><span class="line">b = deepcopy(a) <span class="comment">#深拷贝</span></span><br><span class="line">print(<span class="string">'源对象a--{}:{}'</span>.format(a,[id(x) <span class="keyword">for</span> x <span class="keyword">in</span> a]))</span><br><span class="line">print(<span class="string">'浅拷贝对象b--{}:{}'</span>.format(b,[id(x) <span class="keyword">for</span> x <span class="keyword">in</span> b]))</span><br><span class="line">print(<span class="string">'修改深拷贝对象b'</span>)</span><br><span class="line">b[<span class="number">0</span>] = <span class="string">'world'</span></span><br><span class="line">b[<span class="number">1</span>].append(<span class="number">4</span>)</span><br><span class="line">print(<span class="string">'修改后源对象a--{}:{}'</span>.format(a,[id(x) <span class="keyword">for</span> x <span class="keyword">in</span> a]))</span><br><span class="line">print(<span class="string">'修改后浅拷贝对象b--{}:{}'</span>.format(b,[id(x) <span class="keyword">for</span> x <span class="keyword">in</span> b]))</span><br></pre></td></tr></table></figure><pre><code>源对象a--['hello', [1, 2, 3]]:[2924681864392, 2924682934088]浅拷贝对象b--['hello', [1, 2, 3]]:[2924681864392, 2924681631816]修改深拷贝对象b修改后源对象a--['hello', [1, 2, 3]]:[2924681864392, 2924682934088]修改后浅拷贝对象b--['world', [1, 2, 3, 4]]:[2924682621200, 2924681631816]</code></pre><p>深拷贝就是将里面引用的对象重新创建了一遍并生成了一个新的一系列引用。</p><p>基本上是这样的,但是对于字符串、数字等不可修改的对象来说,重新创建一份似乎有点浪费内存,反正你到时要修改的时候都是新建对象,刷新引用的。所以还用原来的引用也无所谓,还能达到节省内存的目的。</p><p>所以上面的例子中,深拷贝后的b中第一个元素是字符串,所以还是用了原来的引用</p><p>元素不可变的保持原来的引用</p><p>元素可变的马上创建一个一模一样的</p><p>不可变的元素修改后创建新对象,再刷新引用</p><h2 id="浅拷贝的几种方式"><a href="#浅拷贝的几种方式" class="headerlink" title="浅拷贝的几种方式"></a>浅拷贝的几种方式</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 分片表达式能返回一个新的对象拷贝</span></span><br><span class="line"></span><br><span class="line">L = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>]</span><br><span class="line">C = L[<span class="number">1</span>:<span class="number">3</span>]</span><br><span class="line">C[<span class="number">0</span>] = <span class="number">8</span></span><br><span class="line">print(C)</span><br><span class="line">print(L)</span><br></pre></td></tr></table></figure><pre><code>[8, 3][1, 2, 3, 4, 5]</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 字典的copy方法也能够实现字典的完全复制</span></span><br><span class="line"></span><br><span class="line">D = {<span class="string">'a'</span>:<span class="number">1</span>, <span class="string">'b'</span>:<span class="number">2</span>}</span><br><span class="line">B = D.copy()</span><br><span class="line">B[<span class="string">'a'</span>] = <span class="number">888</span></span><br><span class="line">print(B)</span><br><span class="line">print(D)</span><br></pre></td></tr></table></figure><pre><code>{'a': 888, 'b': 2}{'a': 1, 'b': 2}</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 内置函数list可以生成拷贝</span></span><br><span class="line"></span><br><span class="line">L = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>]</span><br><span class="line">C = list(L)</span><br><span class="line">C[<span class="number">0</span>] = <span class="number">888</span></span><br><span class="line">print(C)</span><br><span class="line">print(L)</span><br></pre></td></tr></table></figure><pre><code>[888, 2, 3, 4][1, 2, 3, 4]</code></pre>]]></content>
<summary type="html">
<h2 id="赋值操作认识"><a href="#赋值操作认识" class="headerlink" title="赋值操作认识"></a>赋值操作认识</h2><p>1.赋值是将一个对象的地址赋值给一个变量,让变量指向该地址</p>
<p>2.修改不可变对象(str、tuple)需要开辟新的空间</p>
<p>3修改可变对象(list等)不需要开辟新的空间</p>
</summary>
<category term="Topics" scheme="http://yoursite.com/categories/Topics/"/>
<category term="shallowcopy" scheme="http://yoursite.com/tags/shallowcopy/"/>
<category term="deepcopy" scheme="http://yoursite.com/tags/deepcopy/"/>
</entry>
<entry>
<title>Scope in Python</title>
<link href="http://yoursite.com/2018/04/26/scope/"/>
<id>http://yoursite.com/2018/04/26/scope/</id>
<published>2018-04-25T16:00:00.000Z</published>
<updated>2018-04-28T02:24:42.330Z</updated>
<content type="html"><![CDATA[<p>Python中有作用域链,变量会由内到外找,先去自己作用域去找,自己没有再去上级去找,直到找不到报错</p><a id="more"></a><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">name = <span class="string">"lzl"</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">f1</span><span class="params">()</span>:</span></span><br><span class="line"> name = <span class="string">"Eric"</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">f2</span><span class="params">()</span>:</span></span><br><span class="line"> name = <span class="string">"Snor"</span></span><br><span class="line"> print(name)</span><br><span class="line"> f2()</span><br><span class="line">f1()</span><br></pre></td></tr></table></figure><pre><code>Snor</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">name = <span class="string">"lzl"</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">f1</span><span class="params">()</span>:</span></span><br><span class="line"> name = <span class="string">"Eric"</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">f2</span><span class="params">()</span>:</span></span><br><span class="line"> print(name)</span><br><span class="line"> f2()</span><br><span class="line">f1()</span><br></pre></td></tr></table></figure><pre><code>Eric</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">在函数未执行之前,作用域已经形成了,作用域链也生成了</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">name = <span class="string">"lzl"</span></span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">f1</span><span class="params">()</span>:</span></span><br><span class="line"> print(name)</span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">f2</span><span class="params">()</span>:</span></span><br><span class="line"> name = <span class="string">"eric"</span></span><br><span class="line"> f1()</span><br><span class="line"> </span><br><span class="line">f2()</span><br></pre></td></tr></table></figure><pre><code>lzl</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">name = <span class="string">"lzl"</span></span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">f1</span><span class="params">()</span>:</span></span><br><span class="line"> print(name)</span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">f2</span><span class="params">()</span>:</span></span><br><span class="line"> name = <span class="string">"eric"</span></span><br><span class="line"> <span class="keyword">return</span> f1</span><br><span class="line"> </span><br><span class="line">ret = f2()</span><br><span class="line">ret()</span><br></pre></td></tr></table></figure><pre><code>lzl</code></pre><h2 id="lambda-x-for-x-in-range-10"><a href="#lambda-x-for-x-in-range-10" class="headerlink" title="[lambda :x for x in range(10)]"></a>[lambda :x for x in range(10)]</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">li = [<span class="keyword">lambda</span> :x <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">10</span>)]</span><br><span class="line">print(li)</span><br><span class="line"><span class="keyword">for</span> f <span class="keyword">in</span> li:</span><br><span class="line"> print(f())</span><br></pre></td></tr></table></figure><pre><code>[<function <listcomp>.<lambda> at 0x000001B9CE11F6A8>, <function <listcomp>.<lambda> at 0x000001B9CE11F620>, <function <listcomp>.<lambda> at 0x000001B9CE11F598>, <function <listcomp>.<lambda> at 0x000001B9CE11F2F0>, <function <listcomp>.<lambda> at 0x000001B9CE11F158>, <function <listcomp>.<lambda> at 0x000001B9CE11F268>, <function <listcomp>.<lambda> at 0x000001B9CE11F1E0>, <function <listcomp>.<lambda> at 0x000001B9CE11F488>, <function <listcomp>.<lambda> at 0x000001B9CE11F400>, <function <listcomp>.<lambda> at 0x000001B9CE0742F0>]9999999999</code></pre><p>上面结果所有的都是9,而不是想当然的1-9<br>因为循环10次已经在生产list结束了,所以函数中的x向上找,找到了for循环结束的9<br>然后函数在没有执行前,内部代码不执行<br>上面代码实质如下</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">li = []</span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">10</span>): </span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">niming</span><span class="params">()</span>:</span> <span class="comment">#无参数的函数</span></span><br><span class="line"> <span class="keyword">return</span> x</span><br><span class="line"> li.append(niming)</span><br><span class="line">print(li)</span><br><span class="line"><span class="keyword">for</span> f <span class="keyword">in</span> li:</span><br><span class="line"> print(f())</span><br></pre></td></tr></table></figure><pre><code>[<function niming at 0x000001B9CE0742F0>, <function niming at 0x000001B9CE074AE8>, <function niming at 0x000001B9CE074048>, <function niming at 0x000001B9CE074730>, <function niming at 0x000001B9CE10DF28>, <function niming at 0x000001B9CE10D730>, <function niming at 0x000001B9CE11F0D0>, <function niming at 0x000001B9CE11F378>, <function niming at 0x000001B9CE11F048>, <function niming at 0x000001B9CE11F9D8>]9999999999</code></pre><h2 id="lambda-x-x-x-for-x-in-range-10"><a href="#lambda-x-x-x-for-x-in-range-10" class="headerlink" title="[lambda x=x:x for x in range(10)]"></a>[lambda x=x:x for x in range(10)]</h2><p>把代码稍微修改一下,观察结果</p><p><a href="https://stackoverflow.com/questions/12332500/x-lambda-x-for-x-in-range3-what-will-x0-return" target="_blank" rel="noopener">https://stackoverflow.com/questions/12332500/x-lambda-x-for-x-in-range3-what-will-x0-return</a></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">li = [<span class="keyword">lambda</span> x=x:x <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">10</span>)]</span><br><span class="line"></span><br><span class="line">print(li)</span><br><span class="line"><span class="keyword">for</span> f <span class="keyword">in</span> li:</span><br><span class="line"> print(f())</span><br></pre></td></tr></table></figure><pre><code>[<function <listcomp>.<lambda> at 0x000001B9CE0748C8>, <function <listcomp>.<lambda> at 0x000001B9CE074510>, <function <listcomp>.<lambda> at 0x000001B9CE0741E0>, <function <listcomp>.<lambda> at 0x000001B9CE074AE8>, <function <listcomp>.<lambda> at 0x000001B9CE074A60>, <function <listcomp>.<lambda> at 0x000001B9CE11FE18>, <function <listcomp>.<lambda> at 0x000001B9CE11FEA0>, <function <listcomp>.<lambda> at 0x000001B9CE11FAE8>, <function <listcomp>.<lambda> at 0x000001B9CE11FB70>, <function <listcomp>.<lambda> at 0x000001B9CE11FBF8>]0123456789</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">li = []</span><br><span class="line"><span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">10</span>): </span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">niming</span><span class="params">(x=x)</span>:</span> <span class="comment">#有参数,且是默认参数,所以下面f()不放参数也可以运行 为参数提供默认值,调用函数时可传可不传该默认参数的值</span></span><br><span class="line"> <span class="keyword">return</span> x</span><br><span class="line"> li.append(niming)</span><br><span class="line">print(li)</span><br><span class="line"><span class="keyword">for</span> f <span class="keyword">in</span> li:</span><br><span class="line"> print(f())</span><br></pre></td></tr></table></figure><pre><code>[<function niming at 0x000001B9CE074AE8>, <function niming at 0x000001B9CE074048>, <function niming at 0x000001B9CE074730>, <function niming at 0x000001B9CE11F0D0>, <function niming at 0x000001B9CE11F378>, <function niming at 0x000001B9CE11F048>, <function niming at 0x000001B9CE10D6A8>, <function niming at 0x000001B9CE10DF28>, <function niming at 0x000001B9CE10D730>, <function niming at 0x000001B9CE128C80>]0123456789</code></pre><h2 id="初探函数作用域"><a href="#初探函数作用域" class="headerlink" title="初探函数作用域"></a>初探函数作用域</h2><p>四个作用域:LEGB,即L本地作用域,E内嵌作用域,G全局作用域和B内置作用域。</p><p>在一个函数中定义的是本地作用域,而模块(也就是一个xxx.py文件)中定义的是全局作用域。而内置作用域,我们使用时是直接使用变量名而不需要导入任何模块,比如一些内置的函数名:print等等</p><p>全局作用域的作用范围仅限于单个文件,别被全局二字所迷惑,这里的全局指的是一个文件的顶层的变量名仅对于这个文件内部的代码而言是全局的,在python中听到全局,你就应该想到模块二字。</p><p>再说说本地作用域:每次对函数的调用都创建一个新的本地作用域,赋值的变量名除非声明为全局变量或非本地变量,否则均为本地变量。在默认的情况下,所有函数定义的内部变量名都位于本地作用域(与函数调用相关的)内。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">x = <span class="number">88</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">func</span><span class="params">()</span>:</span></span><br><span class="line"> x = <span class="number">99</span></span><br><span class="line"> print(x)</span><br><span class="line"></span><br><span class="line">func()</span><br><span class="line">print(x)</span><br></pre></td></tr></table></figure><pre><code>9988</code></pre><p>在这一段程序中,本地变量名x覆盖了全局变量名x,此时本地和全局的两个变量虽然都叫x,但他们是完全不同的变量。</p><h2 id="L-E-G-B-变量索引机制"><a href="#L-E-G-B-变量索引机制" class="headerlink" title="L-E-G-B 变量索引机制"></a>L-E-G-B 变量索引机制</h2><p>当在python中使用某个变量名时,python按照L-E-G-B的顺序依次搜索四个作用域,L本地作用域,E即上一层def或者lambda的本地作用域,之后是全局作用域G,最后是内置作用域B,并且在第一处能找到作用名的地方停下来,如果变量名在这一次搜索中没有找到,python会报错。</p><p>变量的LEGB索引机制:对一个变量,首先在本地(函数内)查找;之后查找嵌套函数的本地作用域,然后再是查找当前的全局作用域,最后是内置作用域。</p><p>因此按照LEGB法则中规定的变量搜索顺序,在本地作用域中的变量名是会在本地作用域中覆盖在全局作用域和内置作用域中有相同变量名的变量,全局变量名会覆盖内置的同名变量名。</p><p>这里我们提到的只是在本地作用域去引用或者覆盖全局变量和内置变量。</p><p>但是,请注意!如果试图去修改,即在函数内部试图改变函数外部声明的值,那就得用global和nonlocal关键字了。</p><h3 id="global关键字"><a href="#global关键字" class="headerlink" title="global关键字"></a>global关键字</h3><p>之前我们说过python中的变量不用声明,直接赋值使用,但是这个global关键字看上去就像一个声明,但是他不是一个类型的声明,而是一个变量命名空间的声明,它告诉python函数打算生成一个或多个全局变量。应用他,就可以在函数内部对全局变量进行引用和修改</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">x = <span class="number">88</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">func</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">global</span> x</span><br><span class="line"> x = <span class="number">99</span></span><br><span class="line"></span><br><span class="line">func()</span><br><span class="line">print(x)</span><br></pre></td></tr></table></figure><pre><code>99</code></pre><p>在这个例子中,我们对X加了一个global声明,以便在def之内引用并修改位于全局的变量x,而不是产生一个新的本地变量x并将其覆盖</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">x,y,z = <span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">all_global</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">global</span> x</span><br><span class="line"> x = y + z</span><br><span class="line"></span><br><span class="line">all_global()</span><br><span class="line">print(x)</span><br></pre></td></tr></table></figure><pre><code>5</code></pre><p>这个例子中,x,y,z都是全局变量,y和z只是引用值,而对于x,我们想改变他的值,因此用了global进行引用声明。</p><h3 id="嵌套函数的本地作用域-E"><a href="#嵌套函数的本地作用域-E" class="headerlink" title="嵌套函数的本地作用域 E"></a>嵌套函数的本地作用域 E</h3><p>python有一个很有意思的地方,就是def函数可以嵌套在另一个def函数之中。调用外层函数时,运行到的内层def语句仅仅是完成对内层函数的定义,而不会去调用内层函数,除非在嵌套函数之后又显式的对其进行调用。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">x = <span class="number">99</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">f1</span><span class="params">()</span>:</span></span><br><span class="line"> x = <span class="number">88</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">f2</span><span class="params">()</span>:</span></span><br><span class="line"> print(x)</span><br><span class="line"> f2()</span><br><span class="line"></span><br><span class="line">f1()</span><br></pre></td></tr></table></figure><pre><code>88</code></pre><h3 id="嵌套作用域的一个特殊之处"><a href="#嵌套作用域的一个特殊之处" class="headerlink" title="嵌套作用域的一个特殊之处"></a>嵌套作用域的一个特殊之处</h3><p>本地作用域在函数结束后就立即失效,而嵌套作用域在嵌套的函数返回后却仍然有效。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">f1</span><span class="params">()</span>:</span></span><br><span class="line"> x = <span class="number">88</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">f2</span><span class="params">()</span>:</span></span><br><span class="line"> print(x)</span><br><span class="line"> <span class="keyword">return</span> f2</span><br><span class="line"></span><br><span class="line">action = f1()</span><br><span class="line">action()</span><br></pre></td></tr></table></figure><pre><code>88</code></pre><p>这个例子非常重要,也很有意思,函数f1中定义了函数f2,f2引用了f1嵌套作用域内的变量x,并且f1将函数f2作为返回对象进行返回。最值得注意的是我们通过变量action获取了返回的f2,虽然此时f1函数已经退出结束了,但是f2仍然记住了f1嵌套作用域内的变量名x。</p><p>上面这种语言现象称之为闭包:一个能记住嵌套作用域变量值的函数,尽管作用域已经不存在。</p><h2 id="工厂函数"><a href="#工厂函数" class="headerlink" title="工厂函数"></a>工厂函数</h2><p>这里有一个应用就是工厂函数,工厂函数定义了一个外部的函数,这个函数简单的生成并返回一个内嵌的函数,仅仅是返回却不调用,因此通过调用这个工厂函数,可以得到内嵌函数的一个引用,内嵌函数就是通过调用工厂函数时,运行内部的def语句而创建的</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">maker</span><span class="params">(n)</span>:</span></span><br><span class="line"> k = <span class="number">8</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">action</span><span class="params">(x)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> x ** n + k</span><br><span class="line"> <span class="keyword">return</span> action</span><br><span class="line"></span><br><span class="line">f = maker(<span class="number">2</span>)</span><br><span class="line">print(f)</span><br></pre></td></tr></table></figure><pre><code><function maker.<locals>.action at 0x000001B9CE10DF28></code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">maker</span><span class="params">(n)</span>:</span></span><br><span class="line"> k = <span class="number">8</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">action</span><span class="params">(x)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> x ** n + k</span><br><span class="line"> <span class="keyword">return</span> action</span><br><span class="line"></span><br><span class="line">f = maker(<span class="number">2</span>)</span><br><span class="line">print(f(<span class="number">4</span>))</span><br></pre></td></tr></table></figure><pre><code>24</code></pre><p>这里我们可以看出,内嵌的函数action记住了嵌套作用域内得两个嵌套变量,一个是变量k,一个是参数n,即使后面maker返回并退出。我们通过调用外部的函数maker,得到内嵌的函数action的引用。这种函数嵌套的方法在后面要介绍的装饰器中会经常用到。这种嵌套作用域引用,就是python的函数能够保留状态信息的主要方法了。</p><h2 id="关键字nonlocal"><a href="#关键字nonlocal" class="headerlink" title="关键字nonlocal"></a>关键字nonlocal</h2><p>本地函数通过global声明对全局变量进行引用修改,那么对应的,内嵌函数内部想对嵌套作用域中的变量进行修改,就要使用nonlocal进行声明。</p><p>不是一个类型的声明,而是一个变量命名空间的声明</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">x = <span class="number">88</span> <span class="comment">#全局变量</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">func</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">global</span> x <span class="comment"># 本地函数对全局变量修改,要用 global 声明 </span></span><br><span class="line"> x = <span class="number">99</span></span><br><span class="line"></span><br><span class="line">func()</span><br><span class="line">print(x)</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">test</span><span class="params">(num)</span>:</span></span><br><span class="line"> in_num = num <span class="comment"># 嵌套作用域中的变量 </span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">nested</span><span class="params">(label)</span>:</span></span><br><span class="line"> <span class="keyword">nonlocal</span> in_num <span class="comment">#内嵌函数对嵌套作用域中的变量修改</span></span><br><span class="line"> in_num += <span class="number">1</span></span><br><span class="line"> print(label, in_num)</span><br><span class="line"> <span class="keyword">return</span> nested</span><br><span class="line"></span><br><span class="line">F = test(<span class="number">0</span>)<span class="comment"># test函数已经退出调用,但F仍然记着变量in_num </span></span><br><span class="line">print(F)</span><br><span class="line">F(<span class="string">'a'</span>) <span class="comment">#由于我们使用了nonlocal,就可以在nested函数内修改它</span></span><br><span class="line">F(<span class="string">'a'</span>) <span class="comment">#前面 in_num 已经修改成 1</span></span><br><span class="line">F(<span class="string">'a'</span>) <span class="comment">#前面 in_num 已经修改成 2</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">G = test(<span class="number">100</span>) </span><br><span class="line">G(<span class="string">'mm'</span>)</span><br><span class="line"><span class="comment"># 多次调用工厂函数返回的不同内嵌函数副本F和G,彼此间的内嵌变量in_num是彼此独立隔离的。</span></span><br></pre></td></tr></table></figure><pre><code><function test.<locals>.nested at 0x0000026EBB2B4BF8>a 1a 2a 3mm 101</code></pre><p>我们在nested函数中通过nonlocal关键字引用了内嵌作用域中的变量in_num,那么我们就可以在nested函数中修改他,即使test函数已经退出调用,这个“记忆”依然有效。</p><p>对比下面的例子</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">test</span><span class="params">(num)</span>:</span></span><br><span class="line"> in_num = num <span class="comment"># 嵌套作用域中的变量</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">nested</span><span class="params">(label)</span>:</span></span><br><span class="line"> print(label, in_num) <span class="comment">#本地(函数内)作用域</span></span><br><span class="line"> <span class="keyword">return</span> nested</span><br><span class="line"></span><br><span class="line">F = test(<span class="number">0</span>)<span class="comment"># test函数已经退出调用,但F仍然记着变量in_num </span></span><br><span class="line">print(F)</span><br><span class="line">F(<span class="string">'a'</span>) <span class="comment">#本地作用域中的 in_num 引用了嵌套作用域中的变量 in_num</span></span><br><span class="line">F(<span class="string">'a'</span>) <span class="comment">#in_mun 只是引用,不能修改,所以一直都是0</span></span><br><span class="line">F(<span class="string">'a'</span>) <span class="comment">#in_mun 只是引用,不能修改,所以一直都是0</span></span><br></pre></td></tr></table></figure><pre><code><function test.<locals>.nested at 0x0000026EBB2B4A60>a 0a 0a 0</code></pre>]]></content>
<summary type="html">
<p>Python中有作用域链,变量会由内到外找,先去自己作用域去找,自己没有再去上级去找,直到找不到报错</p>
</summary>
<category term="Topics" scheme="http://yoursite.com/categories/Topics/"/>
<category term="scope" scheme="http://yoursite.com/tags/scope/"/>
</entry>
</feed>