流畅的Python笔记(上)

Python相关知识点准备

一、Python数据类型

  1. Python 数据模型其实就是对Python框架的综述,它规范了这门语言的自身构建模块,包括序列、迭代器、函数、类和上下文管理器。
import collections 
Card = collections.namedtuple('Card',['rank','suit'])
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 suit in self.suits for rank in self.ranks ]
        
    def __len__(self):
        return len(self._cards)
        
    def __getitem__(self,position):
        return self._cards[position]
  1. obj[key] <=> obj.__getitem__(key) 实际上背后实现的原理就是这样的(当碰到特殊的句法的时候Python回使用特殊的方法去激活这些操作)

  2. 这些方法能让语言支持和实现以下的一些特点:(迭代、集合类、属性访问、运算符重载、函数和方法的调用、对象创建和销毁、字符串的形式化和格式化、管理上下文with)

  3. 在以上的程序中,实现了__getitem__的方法,然后就把这个[]索引操作给设定下来了,因为self._cards是列表,所以列表支持索引、支持反向索引、还支持迭代 如果没有实现这个方法就会报错:‘FrenchDeck’ object does not support indexing

  4. 迭代通常是隐式的,我们并没有实现__contains__这个方法,那么in操作符会按顺序做一次迭代搜索,于是in运算符就可以使用for .. in ..就是迭代

  5. 再次声明一点、特殊方法是被python解释器去调用的,我们本身不需要list.__len__() ,可以直接使用len(对象),如果是内置数据类型的调用的话,直接就读取PyVarObject的obj_size 属性,读取一个值比调用方法更快。

  6. 特殊方法的调用很多都是隐式的,比如for i in x:实际上背后调用的是iter(x),我们调用特殊方法的频率要远低于我们去实现它的次数。除了__init__,是为了再子类中调用超类的构造方法。

1.1 有哪些地方隐式调用了特殊方法?

  • for x in items 隐式调用了__contains__,__iter__.if not while not a 调用了__bool__如果没有实现就用__len__. 许多方法都对应了其隐式的方法。with .. open ..上下文管理器调用了__enter__ __exit__。s = Solution(x,y) 就是调用了初始化方法 而且还调用了__new__方法创建一个实例对象。

1.2 __repr__和__str___有什么关系?

  • 他们都是表示一个对象的方式,在输出到控制台或者其他设备时,调用,如果没有实现__str__就会调用__repr__方法,返回的是对象的hashcode 也就是地址。

1.3 obj[key] <=> obj.getitem(key) 索引访问的原理是什么?

  • 把这个[]索引操作给设定下来了,因为self._cards是列表,所以列表支持索引、支持反向索引、还支持迭代 如果没有实现这个方法就会报错。__setitem__赋值的时候就会这样。

1.4 .操作点操作的访问过程是什么?

  • 访问属性、访问方法、访问实例属性、访问类属性、访问数据描述符(覆盖)、访问非数据描述符、就是动态属性的一个访问过程
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 __abs__(self):
        return hypot(self.x,self.y)
    
    def __bool__(self):
        return bool(abs(self))
    
    def __add__(self,other):
        x = self.x + other.x
        y = self.y + other.y
        return Vector(x,y)  #不改变对象本身 只是单纯返回值
    
    def __mul__(self,scalar):
        return Vector(self.x*scalar,self.y*scalar) #乘法交换律被忽略了,在
  1. Python的一个内置函数__repr__ 是能把一个对象利用字符串的形式表达出来,当我们不设定是默认返回对象类别及地址

  2. __repr____str__的区别在于后者只有在print()到终端的时候或者str()函数调用的时候才会被调用,__repr__是最后保障,因为当没有实现__str__时,系统会调用__repr__ https://stackoverflow.com/questions/1436703/difference-between-str-and-repr-in-python 回答得很精彩

  3. bool类型,python中任何要判断的地方如if while not and or 都要触及__bool__这个方法,如果对象不存在这个方法,python回去触发obj.__len__()这一个方法。如果为空则为空

  4. 一个有83个特殊方法,其中有47个用于算术符、位运算、比较操作。

通过实现特殊方法,自定义的数据结构类型可以表现得跟python内置的数据类型一样,从而让我们写出更具有Python风格的代码。
1、数据模型、对象模型
2、元对象所指的是那些对建构语言本身很重要的对象,以此为前提,协议可以看做接口。也就是说,元对象协议是对象模型的同义词,他们的意思都是构建语言的核心API。

1.4 特殊方法一览:(字符串的、数值的、集合的、迭代、属性管理的、实例创建与销毁的、属性描述符)

-w506
-w506
-w571

二、序列构成数组

  1. Python现在的风格:序列的泛型操作、内置的元组和映射类型、用缩进来架构的源码、无需声明变量的强类型。深入理解Python中的不同序列类型,不但能让我们避免重复造轮子、他们的API定义还能帮助我们定义自己的API ,设计得跟原生或者兼容未来可能会出现的类型。

2.1 Python中的序列分为可变序列和不可变序列,可以简单说一下嘛?

  • 不可变:元组、基本数字、str、bytes
  • 可变:list、bytearay、memoryview等,都实现了三个基本的协议就是__iter__ 、__len__ 、__contains__支持不同的操作符,其继承逻辑如下:
  • UML图显示了Python中序列的划分,可以分为可变序列不可变序列。大概共同的方法如下:-w633
    -w558
    -w580

2.2 python2和python3有设么区别吗?

  1. 字符串编码上 在Python2中,有两种字符串类型:str类型和Unicode类型。str就是难以懂的字节数据,unicode就是可以解码用utf-8解码的编码才能正常显示中文、u'一般前面加个u'
    python3中默认把字节数据编码成strutf8的形式可以支持中文。
  2. 在python2中的列表推导式会发生内存泄露、python3修复了这个问题。

2.3 python中类似列表推导式的还有那些?通常用来做什么?

  1. 列表推导式[i for i in range(5)] [[i for i in range(4)] for j in range(5)] [i for i in range(5) if i%2==1]可以取代map\filter等操作。
  2. 字典推导式:{a:b for a in x for b in c} {a:b for a,b in q}自动解包
  3. 生成器表达式:(a for a in c) 迭代器就可以利用生成器懒加载的特性来提高效率。
  4. 列表、元组、字典推导 来生成列表、元组、字典的方式更加易读高效率、但是当代码超过3行的时候就要考虑用for循环来写程序了。(在Python2.7中列表推导没有自己的局部变量域,会使上一个同名变量发生改变,出现变量泄露的情况,在Python3之后就不会有了。)
  5. 列表推导和map、filter 效率比较https://github.com/fluentpython/example-code/blob/master/02-array-seq/listcomp_speed.py
#列表推导能做 filter 和map函数做的事,而且不用借助lambda
symbols = "$#%^$@*&"
beyond_asic = [ord(s) for s in symbols if ord(s) > 127]
beyond_asic1 = list(filter(lambda c :c > 127,map(ord,symbols)))


card = ['A','K','Q']
suit = ['diamond','club','hearts','spades']
result = [(k,v) for k in card for v in suit]#笛卡尔积的感觉

num = {
   (a,b) for a in range(10) for b in range(5)} #生成器表达式 列表推导换成这样

2.4 生成器迭代器和列表推导式的区别以及表达方式

  1. 生成器表达式在初始化序列的时候,比列表推导更加好,因为前者节省了内存,而不是先把一切数据排列好再放入构造器中去完成。只需要把方括号变成圆括号就好了。生成器表达式遵循迭代器协议可以逐个产出元素。
    -w309

2.5 python中的拆包和打包有了解吗?zip(*iterator)

  • 拆包其实就是从元组里面逐个获取元素,zip/pack 就是打包成元组。https://www.python.org/dev/peps/pep-3132/ 任何可迭代对象都可以被拆包,但是唯一一个要求就是目标变量的个数要跟元素个数一致,或者用*来表示忽略个数。还可以用星号*来把可迭代对象拆开作为函数的参数。用*来处理剩下的元素,几种精力在我们想要的元素上,**是字典的不定长参数的表示。
metro_areas = [('Tokyo','JP',36.933,(35.689722,139.691667)),  # ➊
    ('Delhi NCR', 'IN', 21.935, (28.613889, 77.208889)),
    ('Mexico City', 'MX', 20.142, (19.433333, -99.133333))
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值