预备知识
python中类的方法有四种表示方式:xxx, _xxx, __xxx, __xxx__。
xxx: 表示普通方法与属性
_xxx: 表示私有方法与属性,提示其他人在类外使用该方法与属性
__xxx: 子类不能覆盖父类该方法
__xxx__: 特殊属性、特殊方法
特殊属性
__module__: 类、方法、实例的类所在的模块
>>> list.__module__
'__builtin__'
list是一个类,这个类所在模块为内置模块。
>>> import math
>>> math.__module__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute '__module__'
math本身是一个模块,因此没有所在模块这个属性。
>>> math.floor.__module__
'math'
而math模块下面有一个floor方法,这个方法所在模块就是‘math’ 。
那么模块到底是个什么概念呢?
笔者是这样做实验的:
首先在test目录下新建两个文件
appledeMacBook-Air:Documents apple$ cd test
appledeMacBook-Air:test apple$ ls
__init__.py module_test.py
其中init.py文件为空,module_test.py内容如下:
appledeMacBook-Air:test apple$ cat module_test.py
class A():
def a():
print 'pass'
在test路径下,导入类A, 然后输出类、实例、类方法、实例方法的module属性如下:
>>> from module_test import A
>>> A.__module__
'module_test'
>>> A.a.__module__
'module_test'
>>> b = A()
>>> b.__module__
'module_test'
>>> b.a.__module__
'module_test'
在test上一层路径下,导入类A, 然后输出类、实例、类方法、实例方法的module属性如下:
>>> from test.module_test import A
>>> A.__module__
'test.module_test'
__name__: 模块的内置属性
如果直接运行模块,则模块的name属性为main;
如果使用import导入模块,则模块的name属性为导入时的模块名。
doc: 某方法/类/函数的文档。
>>> def a():
... """test"""
... pass
...
>>> a.__doc__
'test'
__dict__:是用来存储对象属性的一个字典.
其键为属性名,值为属性的值。
>>> class A():
... a = 1
... def __init__(self,a):
... self.a = a
...
>>> A.__dict__
{'a': 1, '__module__': '__main__', '__doc__': None, '__init__': <function __init__ at 0x109003578>}
>>> b = A(2)
>>> b.__dict__
{'a': 2}
由上面的例子可以看出,类的__dict__属性与实例的__dict__属性是不同的。
类的__dict__属性包含了方法属性;而实例的__dict__属性却只有常量属性。
__slot__:减小内存
在Python中,每个类都有实例属性。默认情况下Python用一个字典来保存一个对象的实例属性。这非常有用,因为它允许我们在运行时去设置任意的新属性。
然而,对于有着已知属性的小类来说,它可能是个瓶颈。这个字典浪费了很多内存。Python不能在对象创建时直接分配一个固定量的内存来保存所有的属性。因此如果你创建许多对象(我指的是成千上万个),它会消耗掉很多内存。
不过还是有一个方法来规避这个问题。这个方法需要使用slots来告诉Python不要使用字典,而且只给一个固定集合的属性分配空间。
slot介绍来自于文章:
http://blog.csdn.net/qq_35636311/article/details/78248491
特殊方法:
__call__(): 使类实例具有函数作用,具有可调用、可传参的作用。
>>> class A():
... def __call__(self):
... return "__call__()"
...
>>> a = A()
>>> a
<__main__.A instance at 0x1019475a8>
>>> a()
'__call__()'
由上面例子可以看书,实例对象当作函数调用时,实际上调用的是call方法。
__init__():初始化函数。
__new__():创建一个对象。
__str__():打印实例函数。
__enter__() & __exit__():创建上下文使用。
__getattr__() & __setattr__(): 获取和设置对象属性使用。
__getitem__() & __getitem__(): 使类具有字典设置实例的key、value作用。
下面就是一个利用这两个特殊函数实现的不可修改的字典类:
class ImmutableDict(dict):
"""不可修改字典"""
kk = {}
def __init__(self):
super(ImmutableDict, self).__init__()
def __getitem__(self, key):
print "__getitem__"
if self.kk.has_key(key):
return self.kk[key]
else:
return 'no key'
def __setitem__(self, key, value):
print "__setitem__"
if self.kk.has_key(key):
print 'ImmutableDict'
else:
self.kk[key] = value
如下,可以看出当我们调用实例的某个key和设置key对应value时,调用的是__getitem()__,__setitem()__方法。
>>> from immutableDict import ImmutableDict
>>> a = ImmutableDict()
>>> a['a']=1
__setitem__
>>> a['a']=2
__setitem__
ImmutableDict
>>> print a['a']
__getitem__
1
>>> print a['b']
__getitem__
no key
网友评论