美文网首页程序员
python | 类的特殊方法与特殊属性

python | 类的特殊方法与特殊属性

作者: 君子月满楼 | 来源:发表于2017-12-23 20:19 被阅读57次

预备知识

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

参考文章

http://blog.csdn.net/business122/article/details/7568446

相关文章

网友评论

    本文标题:python | 类的特殊方法与特殊属性

    本文链接:https://www.haomeiwen.com/subject/klsnwxtx.html