Python学习笔记(二)

"Python学习笔记"

Posted by jhljx on July 23, 2016

目录

1. Python __slot__属性
2. Python2和Python3除法的比较
3. Python glob模块
4. Python super()方法和__class__属性的关系
5. Reference

1. Python __slot__属性

合理使用__slots__属性可以节省一个对象所消耗的空间。一个普通对象使用一个dict来保存它自己的属性,你可以动态地向其中添加或删除属性,但是如果使用__slots__属性,那么该对象用来保存其自身属性的结构一旦创建则不能再进行任何修改。因此使用slot结构的对象节省了一部分开销。虽然有时这是一个很有用的优化方案,但是它也可能没那么有用,因为如果Python解释器足够动态,那么它完全可以在向对象添加属性时只请求该对象所使用的dict。

2. Python2和Python3除法的比较

python2.x存在有两种除法:

  • 第一,x、y都是整型,运算按整除进行,如\(1/2=0\)。x、y其一为浮点型,就会进行浮点数除法,\(1.0/2=0.5,1/2.0=0.5,1.0/2.0=0.5\)。

  • 第二,板除法即得到不大于结果的最大整数值,这个运算时与操作数无关的。比如,\(1//2=0,1.0//2=0.0,-1//2=-1,-1.0//2=-1.0,1.0//2.0=0.0。\)

python3.x中x/y都是浮点数除法,\(1/2=0.5,-1/2=-0.5\)。\(x//y\)是板除法(整数除法),如下:\(1//2=0,-1//2=-1。\)

在python 2.7中,除法示例如下:

>>> 3 / 2, 3.0 / 2, 3.0 / 2.0
(1, 1.5, 1.5)

3. Python glob模块

glob模块是最简单的模块之一,内容非常少。用它可以查找符合特定规则的文件路径名。跟使用windows下的文件搜索差不多。查找文件只用到三个匹配符:’*’, ‘?’, ‘[]’。 ’*‘匹配0个或多个字符;’?’匹配单个字符;’[]’匹配指定范围内的字符,如:[0-9]匹配数字。

glob.glob返回所有匹配的文件路径列表。它只有一个参数pathname,定义了文件路径匹配规则,这里可以是绝对路径,也可以是相对路径。下面是使用glob.glob的例子:

import glob
#获取指定目录下的所有图片
print(glob.glob(r"E:/Picture/*/*.jpg"))
#获取上级目录的所有.py文件
print(glob.glob(r'../*.py')) #相对路径

glob.iglob获取一个可遍历对象,使用它可以逐个获取匹配的文件路径名。与glob.glob()的区别是:glob.glob同时获取所有的匹配路径,而glob.iglob一次只获取一个匹配路径。这有点类似于.NET中操作数据库用到的DataSet与DataReader。下面是一个简单的例子:

import glob
#父目录中的.py文件
f = glob.iglob(r'../*.py')
print(f) #<generator object iglob at 0x00B9FF80>
for py in f :
    print(py)

4. Python super()方法和__class__属性的关系

python中子类访问父类的属性和方法可以使用super函数。

class A:
  def m(self):
    print('A')

class B(A):
  def m(self):
    print('B')
    super().m()

B().m()

在python2中super函数的用法有所不同。

class A:
  def m(self):
    print('A')

class B(A):
  def m(self):
    print('B')
    super(B, self).m()

B().m()

super()很好地解决了访问父类中的方法的问题。那么,如果要访问父类的父类(准确地说,是方法解析顺序(MRO)中位于第三的类)的属性呢?

比如,B 类是继承 A 的,它重写了 A 的 m 方法。现在我们需要一个 C 类,它需要 B 类的一些方法,但是不要 B 的 m 方法,而改用 A 的。怎么间接地引用到 A 的 m 方法呢?使用self.__class__肯定是不行的,因为 C 还可能被进一步继承。

从文档中我注意到,super 的实现是通过插入一个名为 __class__ 的名字来实现的(super 会从调用栈里去查找这个 __class__ 名字)。所以,就像文档里暗示的,其实可以直接在定义方法时访问 __class__名字,它总是该方法被定义的类。继续我们的单字母类:

class C(B):
  def m(self):
    print('C')
    # see the difference!
    print(__class__.__mro__)
    print(self.__class__.__mro__)
    __class__.__mro__[2].m(self)

class D(C):
  def m(self):
    print('D')
    super().m()

o = D()
o.m()

输出为:

  
D
C
(<class 't.C'>, <class 't.B'>, <class 't.A'>, <class 'object'>)
(<class 't.D'>, <class 't.C'>, <class 't.B'>, <class 't.A'>, <class 'object'>)
A