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
from a import Myclass obj = Myclass() Myclass.__module__ # 输出a obj.__module__ # 输出a
__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)
参考 :http://pycoders-weekly-chinese.readthedocs.io/en/latest/issue6/a-guide-to-pythons-magic-methods.html
浙公网安备 33010602011771号