文章目录
- 魔法方法
- 常用场景及释义
- \_\_new__(cls, [,...])
- \_\_init__
- \_\_del__
- \_\_call__
- \_\_repr__
- \_\_str__
- \_\_bytes__
- \_\_hash__
- \_\_bool__
- \_\_format__
- \_\_getattr__
- \_\_getattribute__
- \_\_setattr__
- \_\_delattr__
- __dir__
- __get__
- __set__
- __delete__
- __it__
- __le__
- __eq__
- __ne__
- __gt__
- __ge__
- __add__
- __sub__
- __mul__
- __truediv__
- __floordiv__
- __mod__
- __divmod__
- __pow__
- 自定义容器
- 上下文管理器(实现了 \_\_enter__和\_\_exit__)
- 对象的序列化
- 运算符
魔法方法
常用场景及释义
__new__(cls, [,…])
__new__才是实例化对象调用的第一个方法,它只取下 cls参数,并把其他参数传给 init
# python2.x单例模式
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __new__(cls, *args, **kwargs):
if not hasattr(cls, 'instance'):
cls.instance = super(Person, cls).__new__(cls)
return cls.instance
__init__
类的初始化操作
__del__
析构函数 当实例被销毁时自动调用
__call__
允许一个类的实例像函数一样被调用
实例被call时候自动调用
__repr__
repr('') 时使用,返回一个方便计算机看的字符串(代表该实例)
__str__
basestring子类
str('')时使用, 返回一个方便人看的字符串(代表该实例)
__bytes__
bytes() 时候调用,必须返回一个 bytes值,否则会报错的
'TypeError: __bytes__ returned non-bytes (type str)'
__hash__
hash()
__bool__
bool()
__format__
__format__(self, formatstr)
^, <, > 分别是居中、左对齐、右对齐,后面带宽度, : 号后面带填充的字符,只能是一个字符,不指定则默认是用空格填充。
+ 表示在正数前显示 +,负数前显示 -; (空格)表示在正数前加空格
b、d、o、x 分别是二进制、十进制、八进制、十六进制。
__getattr__
定义当用户试图访问一个不存在属性的时候的行为
__getattribute__
定义属性被访问时候的行为(属性被访问实际动作)
#注意此处不要用 self.__dict__[item]
#因为self.__dict__依然会被__getattribute__拦截 这样就会陷入循环
__setattr__
定义当一个属性被设置的时候的行为
__delattr__
定义当一个属性被删除的时候的行为
dir
get
set
delete
it
le
eq
ne
gt
ge
add
sub
mul
truediv
floordiv
mod
divmod
pow
自定义容器
- demo
class Task: """ 任务封包 任务划定为: 每个tab的串行 一个tab 及下行数据 是一个任务 """ __slots__ = ["tag", "panel", "block", "timestamp", "status"] def __init__(self): self.tag = None self.panel = None self.block = None self.timestamp = int(time.time()) self.status = 0 def __setitem__(self, key, value): setattr(self, key, value) def __getitem__(self, item): return getattr(self, item) def keys(self): return self.__slots__
__getitem__
__getitem__ 定义获取容器中指定元素的行为,相当于self[key]
__len__
return 数值 标识容器长度 len() 自动调用
__setitem__(self, key, value)
self[key] = value时自动调用的该方法。
__delitem__(self, key)
del self[key]的时自动调用的该方法。
__iter__(self)
return iterator
for x in container:
或iter(container)时自动调用。
__reversed__(self)
內建函数reversed()自动调用该方法====。
__contains__(self, item)
如果定义了该方法,那么在执行item in container 或者 item not in container时该方法就会被调用。
如果没有定义,那么Python会迭代容器中的元素来一个一个比较,从而决定返回True或者False。
__missing__(self, key)
dict字典类型会有该方法,它定义了key如果在容器中找不到时触发的行为。
比如d = {'a': 1}, 当你执行d[notexist]时,d.__missing__('notexist')就会被调用。\
上下文管理器(实现了 __enter__和__exit__)
形如:
with open('1.txt', 'w') as file:
pass
__enter__
__enter__会返回一个值,并赋值给as关键词之后的变量。在这里,你可以定义代码段开始的一些操作。
__exit__
__exit__(self, exception_type, exception_value, traceback)
__exit__定义了代码段结束后的一些操作,可以这里执行一些清除操作,或者做一些代码段结束后需要立即执行的命令,比如文件的关闭,socket断开等。如果代码段成功结束,那么exception_type, exception_value, traceback 三个参数传进来时都将为None。如果代码段抛出异常,那么传进来的三个参数将分别为: 异常的类型,异常的值,异常的追踪栈。
如果__exit__返回True, 那么with声明下的代码段的一切异常将会被屏蔽。
如果__exit__返回None, 那么如果有异常,异常将正常抛出,这时候with的作用将不会显现出来。
对象的序列化
对象的反序列化操作必须要求序列化时, 有序列化时的类存在 比如 <__main__.Class >
TODO
Python对象的序列化操作是pickling进行的。pickling非常的重要,以至于Python对此有单独的模块pickle,还有一些相关的魔术方法。使用pickling, 你可以将数据存储在文件中,之后又从文件中进行恢复。
下面举例来描述pickle的操作。从该例子中也可以看出,如果通过pickle.load 初始化一个对象, 并不会调用__init__方法。
# -*- coding: utf-8 -*-
from datetime import datetime
import pickle
classDistance(object):
def__init__(self, meter):
print 'distance __init__'
self.meter = meter
data = {
'foo': [1, 2, 3],
'bar': ('Hello', 'world!'),
'baz': True,
'dt': datetime(2016, 10, 01),
'distance': Distance(1.78),
}
print 'before dump:', data
with open('data.pkl', 'wb') as jar:
pickle.dump(data, jar) # 将数据存储在文件中
del data
print 'data is deleted!'
with open('data.pkl', 'rb') as jar:
data = pickle.load(jar) # 从文件中恢复数据
print 'after load:', data
值得一提,从其他文件进行pickle.load操作时,需要注意有恶意代码的可能性。另外,Python的各个版本之间,pickle文件可能是互不兼容的。
pickling并不是Python的內建类型,它支持所有实现pickle协议(可理解为接口)的类。pickle协议有以下几个可选方法来自定义Python对象的行为。
__getinitargs__(self)
如果你希望unpickle时,__init__方法能够调用,那么就需要定义__getinitargs__, 该方法需要返回一系列参数的元组,这些参数就是传给__init__的参数。
该方法只对old-style class有效。所谓old-style class,指的是不继承自任何对象的类,往往定义时这样表示: class A:, 而非class A(object):
__getnewargs__(self)
跟__getinitargs__很类似,只不过返回的参数元组将传值给__new__
__getstate__(self)
在调用pickle.dump时,默认是对象的__dict__属性被存储,如果你要修改这种行为,可以在__getstate__方法中返回一个state。state将在调用pickle.load时传值给__setstate__
__setstate__(self, state)
一般来说,定义了__getstate__,就需要相应地定义__setstate__来对__getstate__返回的state进行处理。
__reduce__(self)
如果pickle的数据包含了自定义的扩展类(比如使用C语言实现的Python扩展类)时,就需要通过实现__reduce__方法来控制行为了。由于使用过于生僻,这里就不展开继续讲解了。
令人容易混淆的是,我们知道, reduce()是Python的一个內建函数, 需要指出__reduce__并非定义了reduce()的行为,二者没有关系。
__reduce_ex__(self)
__reduce_ex__ 是为了兼容性而存在的, 如果定义了__reduce_ex__, 它将代替__reduce__ 执行。
下面的代码示例很有意思,我们定义了一个类Slate(中文是板岩的意思)。这个类能够记录历史上每次写入给它的值,但每次pickle.dump时当前值就会被清空,仅保留了历史。
# -*- coding: utf-8 -*-
import pickle
import time
classSlate:
'''Class to store a string and a changelog, and forget its value when pickled.'''
def__init__(self, value):
self.value = value
self.last_change = time.time()
self.history = []
defchange(self, new_value):
# 修改value, 将上次的valeu记录在history
self.history.append((self.last_change, self.value))
self.value = new_value
self.last_change = time.time()
defprint_changes(self):
print 'Changelog for Slate object:'
for k, v in self.history:
print '%s %s' % (k, v)
def__getstate__(self):
# 故意不返回self.value和self.last_change,
# 以便每次unpickle时清空当前的状态,仅仅保留history
return self.history
def__setstate__(self, state):
self.history = state
self.value, self.last_change = None, None
slate = Slate(0)
time.sleep(0.5)
slate.change(100)
time.sleep(0.5)
slate.change(200)
slate.change(300)
slate.print_changes() # 与下面的输出历史对比
with open('slate.pkl', 'wb') as jar:
pickle.dump(slate, jar)
del slate # delete it
with open('slate.pkl', 'rb') as jar:
slate = pickle.load(jar)
print 'current value:', slate.value # None
print slate.print_changes() # 输出历史记录与上面一致
运算符
比较运算符
__eq__(self, other)
定义了比较操作符==的行为.
__ne__(self, other)
定义了比较操作符!=的行为.
__lt__(self, other)
定义了比较操作符<的行为.
__gt__(self, other)
定义了比较操作符>的行为.
__le__(self, other)
定义了比较操作符<=的行为.
__ge__(self, other)
定义了比较操作符>=的行为.
一元运算符
__pos__(self)
实现了'+'号一元运算符(比如+some_object)
__neg__(self)
实现了'-'号一元运算符(比如-some_object)
## 魔法属性
__dict__
类的__dict__属性存储了类定义的所有类属性、类方法等组成的键值对,但不包括继承而来的属性和方法
实例的__dict__属性存储了所有的实例属性的键值对,如果没有就为空;__init__方法其实就是对__dict__属性的初始化赋值;
__doc__
该属性记录了类的说明文档,用类和实例引用指向的都是类的__doc__属性,如果没有默认为None。
__module__
该属性记录类定义的位置,如果定义的位置正好是主程序,那么该值为"_main_",否则是类属于的模块的名字;
__class__
该属性指向该实例的类,即实例指向类对象,类对象指向元类;
__slots__
该属性起到限制动态绑定属性和方法的作用,该属性是一个元组,默认是不存在的,需要手动定义并且只对当前的类起作用,只有添加到元组中的名字才能被动态添加属性,否则报错!
版权声明:本文为weixin_43380311原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。