python特殊方法

在类中经常可以看到一些以双下划线开头结尾的方法,这些称为特殊方法,也叫魔术方法,可以给对象定制一些功能。

__init__

构造函数,初始化的意思,实例化对象时自动执行

class Person(object):

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

# 从Person类实例化出 zhang 对象
zhang = Person('xiaozhang', 20)       // 当执行 Person('xiaozhang', 20) 时实际上是 Person.__init__('zhang', 'xiaozhang', 20),这样分别把'xiaozhang', 20封装在name与age属性中

__str__、__repr__

__str__定义实例调用str()的行为、__repr__定义实例调用repr()的行为

>>> class Student(object):
...     def __init__(self, name, age):
...         self.name = name
...         self.age = age
...     def __str__(self):
...         return '<Student(name={}, age={})>'.format(self.name, self.age)
...     def __repr__(self):
...         return '<Class "{}">'.format(self.__class__.__name__)
... 
>>> s = Student('xxoo', 20)
>>> s                                 # __repr__的效果
<Class "Student">
>>> print(s)                          # __str__的效果
<Student(name=xxoo, age=20)>

__str__是print时的显示,__repr__是在解释器中的显示

__doc__

文档字符串,注释信息,help( 对象 )的时候可以看到

class Person(object):
	""" 类的文档字符串 """
  def __init__(self, name, age):
    self.name = name     self.age = age # print(Person.__doc__) # 类的文档字符串 # print(help(Person)) Help on class Person in module __main__: class Person(builtins.object) | 类的文档字符串 | | Methods defined here: | | __init__(self, name, age) | Initialize self. See help(type(self)) for accurate signature. | | ---------------------------------------------------------------------- | Data descriptors defined here: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined)

__call__

__call__ 让实例对象可以像函数一样支持 " 调用 "

class Person(object):
    """docstring for Foo"""

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

    def __call__(self):
        return dict(name=self.name, age=self.age)

person = Person('myname', 20)
callable(person) --> True # 说明person是一个可调用的对象 person()
--> {'name': 'myname', 'age': 20}

一个应用的场景是作为类装饰器来用

from functools import update_wrapper

class Decorated(object):
    """docstring for Decoated"""

    ENTER = "ENTER.. {}"
    EXIT = "EXIT.. {}"

    def __init__(self, f):
        self.f = f
        update_wrapper(self, f)

    def __call__(self, *args, **kwargs):
        print(Decorated.ENTER.format(self.f.__name__))
        result = self.f(*args, **kwargs)
        print(Decorated.EXIT.format(self.f.__name__))
        return result

@Decorated
def test():
    """docstring for test function"""
    return "hello word!"

__module__

对象所属的模块

class Myclass(object):
    pass
a.py
from a import Myclass


obj = Myclass()

Myclass.__module__   # 输出a
obj.__module__          # 输出a
b.py

__class__

对象所属的类

class Person(object):

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

xiaoming = Person('weimin', 20)     # 实例化出对象xiaoming
xiaoming.__class__                  # <class '__main__.Person'>  // 对象xiaoming 所属的类
xiaoming.__class__.__name__         # Person                   // 对象xiaoming 所属的类名
Person.__class__                    # <class 'type'>         // Person类 所属的类
Person.__class__.__name__        # type                     // Person类 所属的类名

__dict__

类或对象中的所有成员, 类似于命名空间,它是一个dict,键是属性名,值是属性值。 ps:方法也是属性.

class Person(object):

    Country = 'china'     # 静态字段
    __country = 'CHINA'   # 静态私有字段

    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.city = 'beijing'

    def method(self):
        pass

>>> xiaoming = Person('xiaoming', 20)               # 实例化出对象xiaoming
 
>>> xiaoming.__dict__                               # xiaoming(对象)中的所有成员(属性),也就是所有的字段
{'name': 'xiaoming', 'age': 20, 'city': 'beijing'}

>>> Person.__dict__                                 # Person(类)中的所有成员(属性),也就是所有的字段和方法 // 不能修改
mappingproxy({'__module__': '__main__', 'Country': 'china', '_Person__country': 'CHINA', '__init__': <function Person.__init__ at 0x7fb75a7b8488>, 
'method': <function Person.method at 0x7fb75a7b8510>, '__dict__': <attribute '__dict__' of 'Person' objects>, 
'__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None})

__iter__、__next__

__iter__方法可以让对象支持迭代 ( iterable ),像list、dict、str、tuple、set这样的内置数据结构之所以可以迭代是因为对象内部都有个__iter__方法。我们也可以在自定义的对象中添加__iter__方法,返回的必须是一个迭代器。__next__方法可以支持next()函数调用.

class Student(object):
  def __init__(self, name, age):
    self.name = name
    self.age = age

# 从Student类实例化出对象s
s = Student('xiao_hua', 20)

for i in s:   # 尝试迭代,报错TypeError: 'Student' object is not iterable
    print(i)  

因为没有__iter__方法,所以迭代对象时候抛异常, 给对象添加__iter__和__next__方法

from collections import Iterable, Iterator

class Student(object):

    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.index = -1
        self.len = len(self.name)

    def __iter__(self):
        return self

    def __next__(self):
        if self.len == 0:
            raise StopIteration
        
        self.index += 1

        if self.index == self.len:
            raise StopIteration

        return self.name[self.index]

# 根据Student类实例化出对象s
s = Student('huang', 50)

# 判断对象是否为迭代器
isinstance(s, Iterator)     # True

# 判断对象是否为可迭代对象
isinstance(s, Iterable)     # True

# 对象支持next函数
next(s)
next(s)
next(s)
next(s)
next(s)
next(s)   # 报错: StopIteration

# 对象支持for迭代
for i in s:
    print(i, sep='')

__enter__、__exit__

实现了上下文件管理协议,定义清理的动作,常见的比如释放文件、数据库连接资源

当使用with的时候先执行__enter__里面语句,如果有as则将结果返回给as后面的变量,等with里面的语句执行完了则执行__exit__后面的语句,当然还可以处理异常

import pymysql

class mysql(object):

    def __init__(self):
        self.db = pymysql.connect(
            host='192.168.127.210', 
            port=3306, 
            user='access',
            passwd='access', 
            db='learpython', 
            charset='utf8'
        )

    def __enter__(self):
        return self.db

    def __exit__(self, exception_type, exception_value, traceback):
        self.db.close()


with mysql() as db:                      # 当with里面的语句执行完了自动释放文件db资源
    cursor = db.cursor()
    cursor.execute('show tables;')
    data = cursor.fetchall()
    cursor.close()
    print(data)
View Code

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

 

posted @ 2017-04-25 15:04  opss  阅读(206)  评论(0)    收藏  举报