|
61 | 61 | },
|
62 | 62 | {
|
63 | 63 | "cell_type": "code",
|
64 |
| - "execution_count": 2, |
| 64 | + "execution_count": 4, |
65 | 65 | "metadata": {},
|
66 | 66 | "outputs": [
|
67 | 67 | {
|
|
80 | 80 | },
|
81 | 81 | {
|
82 | 82 | "cell_type": "code",
|
83 |
| - "execution_count": 4, |
| 83 | + "execution_count": 5, |
84 | 84 | "metadata": {},
|
85 | 85 | "outputs": [
|
86 | 86 | {
|
|
108 | 108 | },
|
109 | 109 | {
|
110 | 110 | "cell_type": "code",
|
111 |
| - "execution_count": 5, |
| 111 | + "execution_count": 6, |
112 | 112 | "metadata": {},
|
113 | 113 | "outputs": [
|
114 | 114 | {
|
|
136 | 136 | },
|
137 | 137 | {
|
138 | 138 | "cell_type": "code",
|
139 |
| - "execution_count": 6, |
| 139 | + "execution_count": 7, |
140 | 140 | "metadata": {},
|
141 | 141 | "outputs": [
|
142 | 142 | {
|
|
145 | 145 | "(36, 162, 163, 165, 8364, 164)"
|
146 | 146 | ]
|
147 | 147 | },
|
148 |
| - "execution_count": 6, |
| 148 | + "execution_count": 7, |
149 | 149 | "metadata": {},
|
150 | 150 | "output_type": "execute_result"
|
151 | 151 | }
|
|
156 | 156 | },
|
157 | 157 | {
|
158 | 158 | "cell_type": "code",
|
159 |
| - "execution_count": 7, |
| 159 | + "execution_count": 8, |
160 | 160 | "metadata": {},
|
161 | 161 | "outputs": [
|
162 | 162 | {
|
|
183 | 183 | },
|
184 | 184 | {
|
185 | 185 | "cell_type": "code",
|
186 |
| - "execution_count": 8, |
| 186 | + "execution_count": 9, |
187 | 187 | "metadata": {},
|
188 | 188 | "outputs": [
|
189 | 189 | {
|
|
210 | 210 | "cell_type": "markdown",
|
211 | 211 | "metadata": {},
|
212 | 212 | "source": [
|
213 |
| - "# 2.3 元组不仅仅是不可变的列表" |
| 213 | + "## 2.3 元组不仅仅是不可变的列表\n", |
| 214 | + "除了用作不可变的列表,它还可以用于没有字段名的记录\n", |
| 215 | + "\n", |
| 216 | + "### 2.3.1 元组和记录\n", |
| 217 | + "\n", |
| 218 | + "如果只把元组理解为不可变的列表,那其他信息——它所含有的元素的总数和它们的位置——似乎就变得可有可无。但是如果把元组当作一些字段的集合,那么**数量和位置信息**就变得非常重要了。\n", |
| 219 | + "\n", |
| 220 | + "### 2.3.2 元组拆包\n", |
| 221 | + "可以参考Python Techniques系列的笔记\n" |
| 222 | + ] |
| 223 | + }, |
| 224 | + { |
| 225 | + "cell_type": "code", |
| 226 | + "execution_count": 10, |
| 227 | + "metadata": {}, |
| 228 | + "outputs": [ |
| 229 | + { |
| 230 | + "name": "stdout", |
| 231 | + "output_type": "stream", |
| 232 | + "text": [ |
| 233 | + "(2, 4)\n" |
| 234 | + ] |
| 235 | + } |
| 236 | + ], |
| 237 | + "source": [ |
| 238 | + "# * unpacks an iterable\n", |
| 239 | + "t = (20,8)\n", |
| 240 | + "print(divmod(*t))" |
| 241 | + ] |
| 242 | + }, |
| 243 | + { |
| 244 | + "cell_type": "markdown", |
| 245 | + "metadata": {}, |
| 246 | + "source": [ |
| 247 | + "parallel assignment technique" |
| 248 | + ] |
| 249 | + }, |
| 250 | + { |
| 251 | + "cell_type": "code", |
| 252 | + "execution_count": 11, |
| 253 | + "metadata": {}, |
| 254 | + "outputs": [ |
| 255 | + { |
| 256 | + "name": "stdout", |
| 257 | + "output_type": "stream", |
| 258 | + "text": [ |
| 259 | + "0 [1, 2] 3 4\n" |
| 260 | + ] |
| 261 | + } |
| 262 | + ], |
| 263 | + "source": [ |
| 264 | + "a, *body, c, d = range(5)\n", |
| 265 | + "print(a,body,c,d)" |
| 266 | + ] |
| 267 | + }, |
| 268 | + { |
| 269 | + "cell_type": "markdown", |
| 270 | + "metadata": {}, |
| 271 | + "source": [ |
| 272 | + "### 2.3.3 嵌套元组拆包\n", |
| 273 | + "接受表达式的元组可以是嵌套式的,例如(a, b, (c, d))。" |
| 274 | + ] |
| 275 | + }, |
| 276 | + { |
| 277 | + "cell_type": "code", |
| 278 | + "execution_count": 12, |
| 279 | + "metadata": {}, |
| 280 | + "outputs": [ |
| 281 | + { |
| 282 | + "name": "stdout", |
| 283 | + "output_type": "stream", |
| 284 | + "text": [ |
| 285 | + " | lat. | long. \n", |
| 286 | + "Mexico City | 19.4333 | -99.1333\n", |
| 287 | + "New York-Newark | 40.8086 | -74.0204\n", |
| 288 | + "Sao Paulo | -23.5478 | -46.6358\n" |
| 289 | + ] |
| 290 | + } |
| 291 | + ], |
| 292 | + "source": [ |
| 293 | + "# metro_lat_long.py\n", |
| 294 | + "metro_areas = [\n", |
| 295 | + " ('Tokyo', 'JP', 36.933, (35.689722, 139.691667)), # <1>\n", |
| 296 | + " ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),\n", |
| 297 | + " ('Mexico City', 'MX', 20.142, (19.433333, -99.133333)),\n", |
| 298 | + " ('New York-Newark', 'US', 20.104, (40.808611, -74.020386)),\n", |
| 299 | + " ('Sao Paulo', 'BR', 19.649, (-23.547778, -46.635833)),\n", |
| 300 | + "]\n", |
| 301 | + "\n", |
| 302 | + "print('{:15} | {:^9} | {:^9}'.format('', 'lat.', 'long.'))\n", |
| 303 | + "fmt = '{:15} | {:9.4f} | {:9.4f}'\n", |
| 304 | + "for name, cc, pop, (latitude, longitude) in metro_areas: # <2>\n", |
| 305 | + " if longitude <= 0: # <3>\n", |
| 306 | + " print(fmt.format(name, latitude, longitude))" |
| 307 | + ] |
| 308 | + }, |
| 309 | + { |
| 310 | + "cell_type": "markdown", |
| 311 | + "metadata": {}, |
| 312 | + "source": [ |
| 313 | + "### 2.3.4 具名元组(namedtuple)\n", |
| 314 | + "collections.namedtuple是一个**工厂函数**,它可以用来构建一个带字段名的元组和一个有名字的类——这个带名字的类对调试程序有很大帮助。\n", |
| 315 | + "\n", |
| 316 | + "*拓展:工厂函数*\n", |
| 317 | + "\n", |
| 318 | + "In programming, a factory function is a concept used primarily in object-oriented programming. It refers to a function that is designed to create and return new instances of objects. Unlike constructors that are associated with a specific class and are used to create instances of that class, factory functions can be more flexible. They can create objects from multiple classes based on the parameters passed to them or based on specific conditions.\n", |
| 319 | + "\n", |
| 320 | + "Factory functions are useful for several reasons:\n", |
| 321 | + "1. **Abstraction and Encapsulation**: They can hide the complexity of creating instances of complex objects, making the code that uses these objects simpler and cleaner.\n", |
| 322 | + "2. **Flexibility**: Since factory functions are not tied to specific classes, they can return instances of different classes. This makes it easier to introduce new types of objects without changing the code that uses the factory function.\n", |
| 323 | + "3. **Customization**: Parameters passed to a factory function can dictate the customization of the created object, allowing for a more dynamic object creation process.\n", |
| 324 | + "\n", |
| 325 | + "Here's a simple example in JavaScript to illustrate a factory function:\n", |
| 326 | + "\n", |
| 327 | + "```javascript\n", |
| 328 | + "function carFactory(model, year) {\n", |
| 329 | + " return {\n", |
| 330 | + " model: model,\n", |
| 331 | + " year: year,\n", |
| 332 | + " displayInfo: function() {\n", |
| 333 | + " console.log(`Model: ${this.model}, Year: ${this.year}`);\n", |
| 334 | + " }\n", |
| 335 | + " };\n", |
| 336 | + "}\n", |
| 337 | + "\n", |
| 338 | + "const car1 = carFactory('Toyota', 2020);\n", |
| 339 | + "car1.displayInfo(); // Output: Model: Toyota, Year: 2020\n", |
| 340 | + "```\n", |
| 341 | + "\n", |
| 342 | + "In this example, `carFactory` is a factory function that creates and returns a new car object each time it is called. The created car object includes properties for `model` and `year`, as well as a method `displayInfo` to display the car's information. This approach allows for the creation of car objects with different properties without the need for a specific class for each car.\n", |
| 343 | + "\n", |
| 344 | + "书本注:\n", |
| 345 | + "用`namedtuple`构建的类的实例所消耗的内存和元组一样,因为字段名都被存在对应的类内。这个实例比普通的对象实例比起来要小一点,因为python不会用`__dict__`来存放这些实例的属性" |
| 346 | + ] |
| 347 | + }, |
| 348 | + { |
| 349 | + "cell_type": "code", |
| 350 | + "execution_count": 13, |
| 351 | + "metadata": {}, |
| 352 | + "outputs": [], |
| 353 | + "source": [ |
| 354 | + "from collections import namedtuple\n", |
| 355 | + "City = namedtuple('City','name country population coordinates')\n", |
| 356 | + "tokyo = City('Tokyo', 'JP', 36.933, (35.689722, 139.691667))" |
| 357 | + ] |
| 358 | + }, |
| 359 | + { |
| 360 | + "cell_type": "code", |
| 361 | + "execution_count": 14, |
| 362 | + "metadata": {}, |
| 363 | + "outputs": [ |
| 364 | + { |
| 365 | + "name": "stdout", |
| 366 | + "output_type": "stream", |
| 367 | + "text": [ |
| 368 | + "City(name='Tokyo', country='JP', population=36.933, coordinates=(35.689722, 139.691667))\n", |
| 369 | + "Tokyo\n", |
| 370 | + "36.933\n" |
| 371 | + ] |
| 372 | + } |
| 373 | + ], |
| 374 | + "source": [ |
| 375 | + "print(tokyo)\n", |
| 376 | + "print(tokyo.name)\n", |
| 377 | + "print(tokyo.population)" |
| 378 | + ] |
| 379 | + }, |
| 380 | + { |
| 381 | + "cell_type": "markdown", |
| 382 | + "metadata": {}, |
| 383 | + "source": [ |
| 384 | + "*code comment:*\n", |
| 385 | + "1. 创建`namedtuple`需要两个参数,一个是类名,另一个是类的各个字段的名字。后者可以是由数个**字符串组成的可迭代对象**,或者是由**空格分隔开的字段名组成的字符串**。\n", |
| 386 | + "2. 存放在对应字段里的数据要以一串参数的形式传入到构造函数中(元组的构造函数却只接受单一的可迭代对象)\n", |
| 387 | + "3. ...\n", |
| 388 | + "\n", |
| 389 | + "具名元组还有一些自己专有的属性:\n", |
| 390 | + "- `_fields` class attribute\n", |
| 391 | + "- `_make(iterable)` class method\n", |
| 392 | + "- `_asdict()` instance method" |
| 393 | + ] |
| 394 | + }, |
| 395 | + { |
| 396 | + "cell_type": "code", |
| 397 | + "execution_count": 15, |
| 398 | + "metadata": {}, |
| 399 | + "outputs": [ |
| 400 | + { |
| 401 | + "data": { |
| 402 | + "text/plain": [ |
| 403 | + "('name', 'country', 'population', 'coordinates')" |
| 404 | + ] |
| 405 | + }, |
| 406 | + "execution_count": 15, |
| 407 | + "metadata": {}, |
| 408 | + "output_type": "execute_result" |
| 409 | + } |
| 410 | + ], |
| 411 | + "source": [ |
| 412 | + "City._fields" |
| 413 | + ] |
| 414 | + }, |
| 415 | + { |
| 416 | + "cell_type": "code", |
| 417 | + "execution_count": 16, |
| 418 | + "metadata": {}, |
| 419 | + "outputs": [ |
| 420 | + { |
| 421 | + "name": "stdout", |
| 422 | + "output_type": "stream", |
| 423 | + "text": [ |
| 424 | + "{'name': 'Delhi NCR', 'country': 'IN', 'population': 21.935, 'coordinates': LatLong(lat=28.613889, long=77.208889)}\n" |
| 425 | + ] |
| 426 | + } |
| 427 | + ], |
| 428 | + "source": [ |
| 429 | + "LatLong = namedtuple('LatLong', 'lat long') \n", |
| 430 | + "delhi_data = ('Delhi NCR', 'IN', 21.935, LatLong(28.613889, 77.208889)) \n", |
| 431 | + "delhi = City._make(delhi_data) \n", |
| 432 | + "print(delhi._asdict()) " |
| 433 | + ] |
| 434 | + }, |
| 435 | + { |
| 436 | + "cell_type": "code", |
| 437 | + "execution_count": 17, |
| 438 | + "metadata": {}, |
| 439 | + "outputs": [ |
| 440 | + { |
| 441 | + "name": "stdout", |
| 442 | + "output_type": "stream", |
| 443 | + "text": [ |
| 444 | + "name: Delhi NCR\n", |
| 445 | + "country: IN\n", |
| 446 | + "population: 21.935\n", |
| 447 | + "coordinates: LatLong(lat=28.613889, long=77.208889)\n" |
| 448 | + ] |
| 449 | + } |
| 450 | + ], |
| 451 | + "source": [ |
| 452 | + "for key, value in delhi._asdict().items(): \n", |
| 453 | + " print(key + ':', value) " |
| 454 | + ] |
| 455 | + }, |
| 456 | + { |
| 457 | + "cell_type": "markdown", |
| 458 | + "metadata": {}, |
| 459 | + "source": [ |
| 460 | + "*code comment:*\n", |
| 461 | + "1. `_fields`属性是一个包含这个类所有字段名称的元组。\n", |
| 462 | + "2. 用`_make()`通过接受一个可迭代对象来生成这个类的一个实例,它的作用跟`City(*delhi_data)`是一样的。\n", |
| 463 | + "3. `_asdict()`把具名元组以`collections.OrderedDict`的形式返回,我们可以利用它来把元组里的信息清晰的呈现出来。" |
214 | 464 | ]
|
215 | 465 | }
|
216 | 466 | ],
|
|
0 commit comments