前言总结
对于新手来说:
python是一门既容易上手又强大的编程语言
对于程序员来说:
开发者们会慢慢地写出带着“口音”的Python代码
本书:
重点描述:
Python作为编程语言独有的特性
提示:
不要在一开始写程序的时候
过度使用本书的编程技巧
因为:不成熟的抽象和过早的优化一样,都会坏事。
第一部分
Python的数据模型 data model
讲解python的数据模型,以及为了保持一致性而使用特殊方法(魔法方法)
第一部分 序幕
第1章 Python数据模型
Python最好的品质之一是一致性:
当你使用Python工作一会儿后,就会开始理解Python语言,并能正确猜测出对你来说全新的语言特征。
面向对象程序员会对
len(collection)而不是collection.len( )的写法感到不适
这种设计方法是python风格代码的关键:
这种设计思想完全体现在Python的数据模型上
数据模型所描述的API,为使用最地道的语言特性来构建你自己的对象提供了工具
数据模型其实是对Python框架的描述,它规范了这门语言自身构建模块的接口
这些模块包括但不限于:
序列、迭代器、函数、类和上下文管理器。
在数据模型框架之下写程序,会需要大量实现框架本身需要调用的方法
python解释器碰到特殊的句法时,会使用特殊方法去激活一些基本的对象操作,这些特殊方法的名字以两个下划线开头,以两个下划线结尾
这些特殊方法名能让你自己的对象实现和支持以下的语言构架,并与之交互:
迭代
集合类
属性访问
运算符重载
函数和方法的调用
对象的创建和销
1.0数据模型基础
'对象’是python中对数据的抽象,python程序中的所有数据都是由对象或对象之间的关系来表示
a=["python,go"]
b=["python,go"]
c=1
d=1
print(id(a))
print(id(b))
print(type(a))
print(type(b))
print(a is b)
print(a==b)
print("********")
print(id(c))
print(id(d))
print(type(c))
print(type(d))
print(c is d)
print(c==d)
观察python对可变数据和不可变数据(数字、字符串)创建对象时的不同处理
1.1 一摞Python风格的纸牌
通过实现__getitem__和__len__这两个特殊方法展示其强大
```python
在这里插入代码片
```python
```python
```html
```groovy
在这里插入代码片
1.1 一摞Python风格的纸牌
通过实现__getitem__和__len__这两个特殊方法展示其强大
import collections
Card=collections.namedtuple("Card",["rank","suit"])
#创建一个纸牌类
#namedtuple创建只有一些属性没方法的简单类
class FrenchDeck:
ranks=[str(n) for n in range(2,11)]+list("JQKA")
#创建牌值列表
suits='spades diamonds clubs hearts'.split()
#创建花色列表
def __init__(self):
self._cards=[Card(rank,suit) for rank in self.ranks for suit in self.suits]
#初始化一套纸牌列表
def __len__(self):
return len(self._cards)
#实现__len__方法
def __getitem__(self,position):
return self._cards[position]
#实现__getitem__方法
#创建一张纸牌
card_one=Card("7","diamonds")
#创建纸牌对象
deck=FrenchDeck()
仅仅通过实现了__len__方法、__getitem__方法。
对纸牌对象就有了下列操作:
索引:
deck[0]
deck[10]
切片:
deck[0:10]
迭代:
for card in deck:
print(card)
for card in reversed(deck):
print(card)
存在判断:
Card("7","hearts") in deck
len(deck)
随机选择一张牌:
from random import choice
choice(desk)
现在已经可以体会到通过实现特殊方法来利用Python数据模型的两个好处
作为你的类的用户,他们不必去记住标准操作的各式名称
可以更加方便地利用Python的标准库,比如random.choice函数,从而不用重复造轮子
1.2 如何使用特殊方法
特殊方法的存在是为了被Python解释器调用的,你自己并不需要调用它们
len(deck)=deck.len()
通过内置的函数(例如len、iter、str,等等)
来使用特殊方法是最好的选择。这些内置函数不仅会调用特殊方法,
通常还提供额外的好处,而且对于内置的类来说,它们的速度更快
(14.12)
1.2.1 模拟数值类型
实现一个向量数据类型,使用下面这些特殊方法
repr、abs、add__和__mul
from math import hypot #倒入取模运算 class Vector: def __init__(self,x=0,y=0): self.x=x self.y=y def __repr__(self): return "Vector(%r,%r)"%(self.x,self.y) #返回对象的字符串表达形式 def __add__(self,other): x=self.x+other.x y=self.y+other.y return Vector(x,y) #返回两个向量相加的值 def __bool__(self): return bool(abs(self)) #返回向量的布尔值 def __abs__(self): return hypot(self.x,self.y) #返回向量的模 def __mul__(self,scalar): return Vector(self.x*scalar,self.y*scalar) #返回向量和一个数的乘积 测试: a=Vector(1,2) b=Vector(3,4) print(a,b) c=a+b print(c) c=a*3 print(c) c=bool(c) print(c)
1.2.2 字符串表示形式
__repr__ __str__ Python有一个内置的函数叫repr, 它能把一个对象用字符串的形式表达出来以便辨认,这就是“字符串表示形式”。 __repr__ __str__ 的区别: 后者在str()函数被调用、或print()打印一个对象的时候才会调用
1.2.3 算术运算符
通过__add__和__mul__
中缀运算符的基本原则就是不改变操作对象,而是产出一个新的值
1.3 特殊方法一览
Python语言参考手册中的“Data Model”一章列出了83个特殊方法的名字
‘’’
链接:
‘’’
1.4为什么len不是普通方法?
如果x是一个内置类型的实例,那么len(x)的速度会非常快。
背后的原因是CPython会直接从一个C结构体里读取对象的长度,完全不会调用任何方法。
换句话说,len之所以不是一个普通方法,是为了让Python自带的数据结构可以走后门,
但是多亏了它是特殊方法,我们也可以把len用于自定义数据类型。
这种处理方式在保持内置类型的效率和保证语言的一致性之间找到了一个平衡点,
也印证了“Python之禅”中的另外一句话:“不能让特例特殊到开始破坏既定规则
练习:创建一个车牌集合类,车牌有三个属性:号码,城市,消费金额。按照消费金额进行排序。
import collections
import random
car_number=collections.namedtuple("car_number",["number","city","cost"])
#创建一个简单的数字车牌类
#namedtuple创建只有一些属性没方法的简单类
number=[str(n) for n in range(10)]
class CarNumber:
#创建一个车牌集合类
number=[str(n) for n in range(10)]
city_list="shan_A shan_B shan_C shan_D".split()
#创建一个城市列表
number_list=["".join(random.sample(number,6)) for _ in range(10)]
#穿件一个包含10个6位数字的车牌列表
def __init__(self):
self._car_number=[car_number(number,city,cost) for number in self.number_list for city in self.city_list for cost in [50,0]]
#初始化10个车牌的集合类
def __len__(self):
return len(self._car_number)
def __getitem__(self,position):
return self._car_number[position]
#创建一个车牌对象
# car_1=car_number(123456,"shan_A")
#创建一组车牌集合类
carNumber=CarNumber()
print(len(carNumber))
print(carNumber[0:10])
for number in carNumber:
print(number)
#排序
sorted_list=sorted(carNumber,key=lambda x:x.cost)
for i in sorted_list:
print(i)



