-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclass-in-python.html
235 lines (184 loc) · 13.1 KB
/
class-in-python.html
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="HandheldFriendly" content="True" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="robots" content="index, follow" />
<link href="https://fonts.googleapis.com/css2?family=Source+Code+Pro:ital,wght@0,400;0,700;1,400&family=Source+Sans+Pro:ital,wght@0,300;0,400;0,700;1,400&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="https://blog.tonychow.me/theme/stylesheet/style.min.css">
<link id="pygments-light-theme" rel="stylesheet" type="text/css"
href="https://blog.tonychow.me/theme/pygments/colorful.min.css">
<link rel="stylesheet" type="text/css" href="https://blog.tonychow.me/theme/font-awesome/css/fontawesome.css">
<link rel="stylesheet" type="text/css" href="https://blog.tonychow.me/theme/font-awesome/css/brands.css">
<link rel="stylesheet" type="text/css" href="https://blog.tonychow.me/theme/font-awesome/css/solid.css">
<link href="https://blog.tonychow.me/feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="Tonychow's Blog Atom">
<!-- Chrome, Firefox OS and Opera -->
<meta name="theme-color" content="#333333">
<!-- Windows Phone -->
<meta name="msapplication-navbutton-color" content="#333333">
<!-- iOS Safari -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<!-- Microsoft EDGE -->
<meta name="msapplication-TileColor" content="#333333">
<meta name="author" content="tonychow" />
<meta name="description" content="" />
<meta name="keywords" content="python">
<meta property="og:site_name" content="Tonychow's Blog"/>
<meta property="og:title" content="Python 中的 New-style 和 Old-style classes"/>
<meta property="og:description" content=""/>
<meta property="og:locale" content="en_US"/>
<meta property="og:url" content="https://blog.tonychow.me/class-in-python.html"/>
<meta property="og:type" content="article"/>
<meta property="article:published_time" content="2013-04-06 00:00:00+08:00"/>
<meta property="article:modified_time" content=""/>
<meta property="article:author" content="https://blog.tonychow.me/author/tonychow.html">
<meta property="article:section" content="python"/>
<meta property="article:tag" content="python"/>
<meta property="og:image" content="/images/avatar.jpg">
<title>Tonychow's Blog – Python 中的 New-style 和 Old-style classes</title>
</head>
<body class="light-theme">
<aside>
<div>
<a href="https://blog.tonychow.me/">
<img src="/images/avatar.jpg" alt="" title="">
</a>
<h1>
<a href="https://blog.tonychow.me/"></a>
</h1>
<p>Go/Python backend developer</p>
<ul class="social">
<li>
<a class="sc-github" href="https://github.com/chow1937" target="_blank">
<i class="fab fa-github"></i>
</a>
</li>
</ul>
</div>
</aside>
<main>
<nav>
<a href="https://blog.tonychow.me/">Home</a>
<a href="/archives.html">Archives</a>
<a href="/categories.html">Categories</a>
<a href="/tags.html">Tags</a>
<a href="https://blog.tonychow.me/feeds/all.atom.xml">Atom</a>
</nav>
<article class="single">
<header>
<h1 id="class-in-python">Python 中的 New-style 和 Old-style classes</h1>
<p>
Posted on 六 06 四月 2013 in <a href="https://blog.tonychow.me/category/python.html">python</a>
• 1 min read
</p>
</header>
<div>
<h3>使用 super() 的错误</h3>
<p>super 函数是 Python 中的一个内置函数,提供对继承的类的函数调用,特别是在子类中被 overridden 的父类函数,比如 </p>
<div class="highlight"><pre><span></span><code><span class="fm">__init__</span><span class="p">()</span>
</code></pre></div>
<p>最近在使用 super 函数的时候出现了个错误,例如下:</p>
<div class="highlight"><pre><span></span><code><span class="o">>>></span> <span class="k">class</span> <span class="nc">Base</span><span class="p">:</span>
<span class="o">...</span> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="o">...</span> <span class="bp">self</span><span class="o">.</span><span class="n">num</span> <span class="o">=</span> <span class="mi">1</span>
<span class="o">...</span>
<span class="o">>>></span> <span class="k">class</span> <span class="nc">Next</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
<span class="o">...</span> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="o">...</span> <span class="nb">super</span><span class="p">(</span><span class="n">Next</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="fm">__init__</span><span class="p">()</span>
<span class="o">...</span>
<span class="o">>>></span> <span class="n">obj</span> <span class="o">=</span> <span class="n">Next</span><span class="p">()</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="s2">"<stdin>"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="n">File</span> <span class="s2">"<stdin>"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">3</span><span class="p">,</span> <span class="ow">in</span> <span class="fm">__init__</span>
<span class="ne">TypeError</span><span class="p">:</span> <span class="n">must</span> <span class="n">be</span> <span class="nb">type</span><span class="p">,</span> <span class="ow">not</span> <span class="n">classobj</span>
</code></pre></div>
<p>可以看到抛出了参数类型错误的错误.一开始完全不知所措,然后将出错信息 google 了一下,找到了解决方式:</p>
<div class="highlight"><pre><span></span><code><span class="o">>>></span> <span class="k">class</span> <span class="nc">Base</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="o">...</span> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="o">...</span> <span class="bp">self</span><span class="o">.</span><span class="n">num</span> <span class="o">=</span> <span class="mi">1</span>
<span class="o">...</span>
<span class="o">>>></span> <span class="k">class</span> <span class="nc">Next</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
<span class="o">...</span> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="o">...</span> <span class="nb">super</span><span class="p">(</span><span class="n">Next</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="fm">__init__</span><span class="p">()</span>
<span class="o">...</span>
<span class="o">>>></span> <span class="n">obj</span> <span class="o">=</span> <span class="n">Next</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">obj</span><span class="o">.</span><span class="n">num</span>
<span class="mi">1</span>
<span class="o">>>></span>
</code></pre></div>
<p>简单地将 Base 继承 object 就可以解决这个错误.其实这是 Python 中的 NewStyle classes 和 OldStyle classes 而导致的一个问题. super() 函数只适用于 NewStyle classes.</p>
<h3>Newstyle 和 Oldstyle</h3>
<p>Python 中,直至 Python2.1 ,类和类型是两种不相关的概念,例如:</p>
<div class="highlight"><pre><span></span><code><span class="o">>>></span> <span class="k">class</span> <span class="nc">Test</span><span class="p">:</span>
<span class="o">...</span> <span class="k">pass</span>
<span class="o">...</span>
<span class="o">>>></span> <span class="n">Test</span><span class="p">()</span><span class="o">.</span><span class="vm">__class__</span>
<span class="o"><</span><span class="k">class</span> <span class="nc">__main__</span><span class="o">.</span><span class="n">Test</span> <span class="n">at</span> <span class="mh">0xb77373ec</span><span class="o">></span>
<span class="o">>>></span> <span class="nb">type</span><span class="p">(</span><span class="n">Test</span><span class="p">())</span>
<span class="o"><</span><span class="nb">type</span> <span class="s1">'instance'</span><span class="o">></span>
<span class="o">>>></span> <span class="nb">type</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">Test</span><span class="p">()))</span>
<span class="o"><</span><span class="nb">type</span> <span class="s1">'type'</span><span class="o">></span>
<span class="o">>>></span>
</code></pre></div>
<p>在这里 Test 类是 Oldstyle 的类.可以看到,Test 类的一个实例,它的类是 Test,但是类型却是 instance.这是因为 Oldstyle 的类与类型是不统一的概念, Oldstyle 类的实例是独立于它们的类,由一个 Python 内置类型 instance 实现的.</p>
<p>从2.2开始, Python 开始使用 New-style 类来统一类和类型.对于一个 New-style 的类,它的实例的类型和类都是一致的.为了兼容之前的代码,在 Python2.2 之后,默认的类定义还是 Old-style 的类.而一个 New-style 的类可以通过继承一个 New-style 的类或者在类继承中最顶端继承 object 来实现,如下:</p>
<div class="highlight"><pre><span></span><code><span class="o">>>></span> <span class="k">class</span> <span class="nc">Test</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="o">...</span> <span class="k">pass</span>
<span class="o">...</span>
<span class="o">>>></span> <span class="n">Test</span><span class="p">()</span><span class="o">.</span><span class="vm">__class__</span>
<span class="o"><</span><span class="k">class</span> <span class="err">'</span><span class="nc">__main__</span><span class="o">.</span><span class="n">Test</span><span class="s1">'></span>
<span class="o">>>></span> <span class="nb">type</span><span class="p">(</span><span class="n">Test</span><span class="p">())</span>
<span class="o"><</span><span class="k">class</span> <span class="err">'</span><span class="nc">__main__</span><span class="o">.</span><span class="n">Test</span><span class="s1">'></span>
<span class="o">>>></span> <span class="nb">type</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">Test</span><span class="p">()))</span>
<span class="o"><</span><span class="nb">type</span> <span class="s1">'type'</span><span class="o">></span>
<span class="o">>>></span>
</code></pre></div>
<p>New-style 类的提出是为了统一 Python的 对象模型.在 Python3 中,Old-style 类已经完全移除了.</p>
<p>参考资料:</p>
<ul>
<li>http://docs.python.org/2/library/functions.html#super</li>
<li>http://docs.python.org/2/reference/datamodel.html#newstyle</li>
<li>http://stackoverflow.com/questions/9698614/super-raises-typeerror-must-be-type-not-classobj-for-new-style-class</li>
<li>http://stackoverflow.com/questions/9699591/instance-is-an-object-but-class-is-not-a-subclass-of-object-how-is-this-po/9699961#9699961</li>
</ul>
</div>
<div class="tag-cloud">
<p>
<a href="https://blog.tonychow.me/tag/python.html">python</a>
</p>
</div>
</article>
<footer>
<p>
© 2017 - This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/deed.en_US" target="_blank">Creative Commons Attribution-ShareAlike</a>
</p>
<p>
Built with <a href="http://getpelican.com" target="_blank">Pelican</a> using <a href="http://bit.ly/flex-pelican" target="_blank">Flex</a> theme
</p><p>
<a rel="license"
href="http://creativecommons.org/licenses/by-sa/4.0/"
target="_blank">
<img alt="Creative Commons License"
title="Creative Commons License"
style="border-width:0"
src="https://i.creativecommons.org/l/by-sa/4.0/80x15.png"
width="80"
height="15"/>
</a>
</p> </footer>
</main>
<script type="application/ld+json">
{
"@context" : "http://schema.org",
"@type" : "Blog",
"name": " Tonychow's Blog ",
"url" : "https://blog.tonychow.me",
"image": "/images/avatar.jpg",
"description": "tonychow's Thoughts and Writings"
}
</script>
</body>
</html>