Python_5

特殊方法与多范式

Python的多范式依赖于Python对象中的特殊方法(special method)。
特殊方法:名字前后各有两个下划线,定义了许多Python 语法和表达方式。

1、运算符

eg:

‘abc’ + ‘xyz’ # 连接字符串

实际执行了如下操作:

‘abc’.add(‘xyz’)

2、内置函数

eg:

len([1,2,3]) # 返回表中元素的总数

实际上做的是:

[1,2,3].len()

3、表(list)元素引用

eg:

常见的表元素引用方式:

li = [1, 2, 3, 4, 5, 6]
print(li[3])

实际上

li = [1, 2, 3, 4, 5, 6]
print(li.getitem(3))

4、函数

任何一个有call()特殊方法的对象都被当作是函数。

eg:

1
2
3
4
5
6
7
class SampleMore(object):
def __call__(self, a):
return a + 5
add = SampleMore() # add为SampleMore类的一个对象
print(add(2)) # 当被调用时,add执行加5的操作
map(add, [2, 4, 5]) # add作为函数对象,被传递给map()函数

上下文管理器

用于规定某个对象的使用范围。一旦进入或者离开该使用范围,会有特殊操作被调用 (比如为对象分配或者释放内存)。
语法形式是with…as…

1、关闭文件

上下文管理器可以在不需要文件的时候,自动关闭文件。

eg1:

1
2
3
4
5
6
# without context manager
f = open("new.txt", "w")
print(f.closed) # whether the file is open
f.write("Hello World!")
f.close()
print(f.closed)

eg2:

1
2
3
4
5
# with context manager
with open("new.txt", "w") as f:
print(f.closed)
f.write("Hello World!")
print(f.closed)

eg2使用了上下文管理器 (with…as…)。
上下文管理器有隶属于它的程序块。当隶属的程序块执行结束的时候(也就是不再缩进),上下文管理器自动关闭了文件 (我们通过f.closed来查询文件是否关闭)。我们使用缩进规定了文件对象f的使用范围
上面的上下文管理器基于f对象的exit()特殊方法

2、自定义

任何定义了enter()和exit()方法的对象都可以用于上下文管理器。
下面,我们自定义用于上下文管理器的对象,就是下面的myvow:

1
2
3
4
5
6
7
8
9
10
11
12
13
class VOW(object):
def __init__(self,text):
self.text = text
def __enter__(self):
self.text = "I say: " + self.text # add prefix
return self # note: return an object
def __exit__(self,exc_type,exc_value,traceback):
self.text = self.text + "!" # add suffix
with VOW("I'm fine") as myvow:
print(myvow.text)
print(myvow.text)

运行结果如下:

I say: I’m fine
I say: I’m fine!

在进入上下文和离开上下文时,对象的text属性发生了改变(最初的text属性是”I’m fine”)。
enter()返回一个对象。上下文管理器会使用这一对象作为as所指的变量,也就是myvow。在enter()中,我们为myvow.text增加了前缀 (“I say: “)。在exit()中,我们为myvow.text增加了后缀(“!”)。

对象的属性

1、属性的dict系统

对象的属性储存在对象的dict属性中。dict为一个词典,键为属性名,对应的值为属性本身。

1
2
3
4
5
6
7
8
9
10
11
12
13
class bird(object):
feather = True
class chicken(bird):
fly = False
def __init__(self, age):
self.age = age
summer = chicken(2)
print(bird.__dict__)
print(chicken.__dict__)
print(summer.__dict__)

运行结果:

1
2
3
4
5
{'__dict__': <attribute '__dict__' of 'bird' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'bird' objects>, 'feather': True, '__doc__': None}
{'fly': False, '__module__': '__main__', '__doc__': None, '__init__': <function __init__ at 0x2b91db476d70>}
{'age': 2}

2、特性

特性是特殊的属性。
比如我们为chicken类增加一个特性adult。当对象的age超过1时,adult为True;否则为False:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class bird(object):
feather = True
class chicken(bird):
fly = False
def __init__(self, age):
self.age = age
def getAdult(self):
if self.age > 1.0: return True
else: return False
adult = property(getAdult)
summer = chicken(2)
print(summer.adult)
summer.age = 0.5
print(summer.adult)

特性使用内置函数property()来创建。
property()最多可以加载四个参数。前三个参数为函数,分别用于处理查询特性、修改特性、删除特性。最后一个参数为特性的文档,可以为一个字符串,起说明作用。

eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class num(object):
def __init__(self, value):
self.value = value
def getNeg(self):
return -self.value
def setNeg(self, value):
self.value = -value
def delNeg(self):
print("value also deleted")
del self.value
neg = property(getNeg, setNeg, delNeg, "I'm negative")
x = num(1.1)
print(x.neg)
x.neg = -22
print(x.value)
print(num.neg.__doc__)
del x.neg

num为一个数字,而neg为一个特性,用来表示数字的负数。当一个数字确定的时候,它的负数总是确定的;而当我们修改一个数的负数时,它本身的值也应该变化。这两点由getNeg和setNeg来实现。而delNeg表示的是,如果删除特性neg,那么应该执行的操作是删除属性value。property()的最后一个参数(“I’m negative”)为特性negative的说明文档。

**3、使用特殊方法getattr

可以用getattr(self, name)来查询即时生成的属性。当我们查询一个属性时,如果通过dict方法无法找到该属性,那么Python会调用对象的getattr方法,来即时生成该属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class bird(object):
feather = True
class chicken(bird):
fly = False
def __init__(self, age):
self.age = age
def __getattr__(self, name):
if name == 'adult':
if self.age > 1.0: return True
else: return False
else: raise AttributeError(name)
summer = chicken(2)
print(summer.adult)
summer.age = 0.5
print(summer.adult)
print(summer.male)