python的__call__、__str__、__repr__、__init__、__class__、__name___、__all__、__doc__、__del__等魔术方法的作用

python中,一切都是对象

在Python中,所有以“__”双下划线包起来的方法,都统称为“Magic Method”--魔术方法

 

1、__call__:作用是把类实例变成一个可调用对象

在Python中,函数其实是一个对象:

>>> f = abs
>>> f.__name__
'abs'
>>> f(-123)
123
由于 f 可以被调用,所以,f 被称为可调用对象。

所有的函数都是可调用对象。
所有的函数都默认实现了方法"__call__",所以所有的函数的都是可以被调用的
>>> def f():
...  print 2
...
>>> f.__name__
'f'
>>> f.__call__
<method-wrapper '__call__' of function object at 0x10d0ec230>
>>> 一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__call__()。 我们把 Person 类变成一个可调用对象: class Person(object): def __init__(self, name, gender): self.name = name self.gender = gender def __call__(self, friend): print 'My name is %s...' % self.name print 'My friend is %s...' % friend 现在可以对 Person 实例直接调用: >>> p = Person('Bob', 'male') >>> p('Tim') My name is Bob... My friend is Tim... 单看 p('Tim') 你无法确定 p 是一个函数还是一个类实例,所以,在Python中,函数也是对象,对象和函数的区别并不显著。

但是如果,你这样定义类,不实现__call__():
class Person(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

 >>> p=Person('Bob','male')
 >>> p
 <__main__.Person object at 0x1081a5e90>
 >>> p('Tim')
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: 'Person' object is not callable

2、__str__:作用是把一个类的实例变成 str,打印显示

    __repr__:作用是调用对象的返回值,

举例见差别:

 

未定义__str__()函数的情况
>>> class Person(object): ... def __init__(self, name, gender): ... self.name = name ... self.gender = gender ... >>> p=Person('Bob','male') >>> p <__main__.Person object at 0x108210490> >>> print p <__main__.Person object at 0x108210490>

定义__str__()函数,但是未定义__repr__()的情况:
>>> class Person(object): ... def __init__(self, name, gender): ... self.name = name ... self.gender = gender ... def __str__(self): ... return '(Person: %s, %s)' % (self.name, self.gender) ... >>> p = Person('Bob','male') >>> p <__main__.Person object at 0x1081a5e90> >>> print p (Person: Bob, male)
同时定义__str__和__repr__的情况:
>>> class Person(object): ... def __init__(self, name, gender): ... self.name = name ... self.gender = gender ... def __str__(self): ... return '(Person: %s, %s)' % (self.name, self.gender) ... __repr__=__str__ ... >>> p = Person('Bob','male') >>> p (Person: Bob, male) >>> print p (Person: Bob, male) >>>
分别定义__str__和__repr__的情况:
>>> class Person(object):
...     def __init__(self, name, gender):
...         self.name = name
...         self.gender = gender
...     def __str__(self):
...         return '(Person: %s, %s)' % (self.name, self.gender)
...     def __repr__(self):
...        return 'xxxx'
...
>>> p=Person('Bob','male')
>>> p
xxxx
>>> print p
(Person: Bob, male)
>>>

 3、__init__:作用是class的初始化函数,类似于Java/C++里的构造函数

 4、__class__:作用,class的实例直接调用就表示生成实例的类

>>> class A:
...     def __init__(self,url):
...         self.url = url
...     def out(self):
...         return self.url
...
>>>
>>> a = A('news.163.com')
>>> print a.out()
news.163.com
>>>
>>> b = a.__class__('www.bccn.net')
>>> print b.out()
www.bccn.net
>>>
>>>
>>> print A
__main__.A
>>> print a.__class__
__main__.A
>>>

还有一种用法:
>>> def foo():
...  pass
...
>>> foo.__class__
<type 'function'>
>>> foo.__name__
'foo'
>>>

 5、__name__:表示函数的名字

>>> def a():
...   print 2
...
>>> f=a
>>> f.__name__
'a'
>>> f
<function a at 0x103996320>
>>> f()
2
>>> f=a()
2
>>> f
>>> f.__name__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute '__name__'
>>>

 6、__slots__:用来限制class的实例动态添加属性: https://eastlakeside.gitbooks.io/interpy-zh/content/slots_magic/

由于Python是动态语言,任何实例在运行期都可以动态地添加属性。

如果要限制添加的属性,例如,Student类只允许添加 name、gender和score 这3个属性,就可以利用Python的一个特殊的__slots__来实现。

顾名思义,__slots__是指一个类允许的属性列表class Student(object):
    __slots__ = ('name', 'gender', 'score')
    def __init__(self, name, gender, score):
        self.name = name
        self.gender = gender
        self.score = score
现在,对实例进行操作:

>>> s = Student('Bob', 'male', 59)
>>> s.name = 'Tim' # OK
>>> s.score = 99 # OK
>>> s.grade = 'A'
Traceback (most recent call last):
  ...
AttributeError: 'Student' object has no attribute 'grade'
__slots__的目的是限制当前类所能拥有的属性,如果不需要添加任意动态的属性,使用__slots__也能节省内存
可以使用工具ipython_memory_usage验证__slots__在节省内存上的作用,这个工具可以计算出每一条命令行使用的内存大小。安装这个工具的时候,mac下建议使用virtualenv环境,减免冲突问题: https://github.com/ianozsvald/ipython_memory_usage
class Person(object):

    __slots__ = ('name', 'gender')

    def __init__(self, name, gender):
        self.name = name
        self.gender = gender

class Student(Person):

    __slots__ = ('score',)

    def __init__(self,name,gender,score):
        super(Student,self).__init__(name,gender)
        self.score=score

s = Student('Bob', 'male', 59)
s.name = 'Tim'
s.score = 99
print s.score
复制代码

 7、__all__的作用参见http://www.cnblogs.com/shengulong/p/7425088.html,主要用例class向外暴露接口

8、__doc__该属性用于描述该对象的作用。

9、__del__:与__init__构造函数相反,它是一个析构函数。

  创建对象后,python解释器默认调用__init__()方法。当删除一个对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法。在python中,对于开发者来说很少会直接销毁对象(如果需要,应该使用del关键字销毁)。Python的内存管理机制能够很好的胜任这份工作。也就是说,不管是手动调用del还是由python自动回收都会触发__del__方法执行。

  举例:__del__对象只要在这个对象真正被删除时才会被调用。

import time
class Animal(object):
    # 初始化方法
    # 创建完对象后会自动被调用
    def __init__(self, name):
        print('__init__方法被调用')
        self.__name = name 

    # 析构方法
    # 当对象被删除时,会自动被调用
    def __del__(self):
        print("__del__方法被调用")
        print("%s对象马上被干掉了..."%self.__name)

# 创建对象
dog = Animal("哈皮狗")

# 删除对象
del dog

cat = Animal("波斯猫")
cat2 = cat
cat3 = cat
print("---马上 删除cat对象")
del cat
print("---马上 删除cat2对象")
del cat2
print("---马上 删除cat3对象")
del cat3 # 这个时候,__del__对象才会被调用

 

 

 

 

http://python.jobbole.com/88367/

https://pycoders-weekly-chinese.readthedocs.io/en/latest/issue6/a-guide-to-pythons-magic-methods.html

posted @ 2017-08-31 08:43  脚本小娃子  阅读(1325)  评论(0编辑  收藏  举报