文章目录
-
- 魔法方法
-
- 常用场景及释义
-
- \_\_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__
- 自定义容器
-
- \_\_getitem__
- \_\_len__
- \_\_setitem__(self, key, value)
- \_\_delitem__(self, key)
- \_\_iter__(self)
- \_\_reversed__(self)
- \_\_contains__(self, item)
- \_\_missing__(self, key)
- 上下文管理器(实现了 \_\_enter__和\_\_exit__)
-
- \_\_enter__
- \_\_exit__
- 对象的序列化
-
- TODO
- 运算符
-
- 比较运算符
- \_\_eq__(self, other)
- \_\_ne__(self, other)
- \_\_lt__(self, other)
- \_\_gt__(self, other)
- \_\_le__(self, other)
- \_\_ge__(self, other)
- 一元运算符
- \_\_pos__(self)
- \_\_neg__(self)
- \_\_dict__
- \_\_doc__
- \_\_module__
- \_\_class__
- \_\_slots__
魔法方法
常用场景及释义
__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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
__init__
类的初始化操作
- 1
- 2
__del__
析构函数 当实例被销毁时自动调用
- 1
- 2
__call__
允许一个类的实例像函数一样被调用
实例被call时候自动调用
- 1
- 2
- 3
__repr__
repr('') 时使用,返回一个方便计算机看的字符串(代表该实例)
- 1
- 2
__str__
basestring子类
str('')时使用, 返回一个方便人看的字符串(代表该实例)
- 1
- 2
- 3
__bytes__
bytes() 时候调用,必须返回一个 bytes值,否则会报错的
'TypeError: __bytes__ returned non-bytes (type str)'
- 1
- 2
- 3
- 4
__hash__
hash()
- 1
__bool__
bool()
- 1
__format__
__format__(self, formatstr)
^, <, > 分别是居中、左对齐、右对齐,后面带宽度, : 号后面带填充的字符,只能是一个字符,不指定则默认是用空格填充。
+ 表示在正数前显示 +,负数前显示 -; (空格)表示在正数前加空格
b、d、o、x 分别是二进制、十进制、八进制、十六进制。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
__getattr__
定义当用户试图访问一个不存在属性的时候的行为
- 1
- 2
__getattribute__
定义属性被访问时候的行为(属性被访问实际动作)
#注意此处不要用 self.__dict__[item]
#因为self.__dict__依然会被__getattribute__拦截 这样就会陷入循环
- 1
- 2
- 3
- 4
__setattr__
定义当一个属性被设置的时候的行为
- 1
- 2
- 3
__delattr__
定义当一个属性被删除的时候的行为
- 1
- 2
dir
- 1
get
- 1
set
- 1
delete
- 1
it
- 1
- 2
le
- 1
- 2
eq
- 1
ne
- 1
gt
ge
add
sub
- 1
mul
- 1
truediv
- 1
floordiv
- 1
mod
divmod
- 1
- 2
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__
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
__getitem__
__getitem__ 定义获取容器中指定元素的行为,相当于self[key]
- 1
__len__
return 数值 标识容器长度 len() 自动调用
- 1
- 2
__setitem__(self, key, value)
self[key] = value时自动调用的该方法。
- 1
- 2
- 3
__delitem__(self, key)
del self[key]的时自动调用的该方法。
- 1
__iter__(self)
return iterator
for x in container:
或iter(container)时自动调用。
- 1
- 2
- 3
__reversed__(self)
內建函数reversed()自动调用该方法====。
- 1
__contains__(self, item)
如果定义了该方法,那么在执行item in container 或者 item not in container时该方法就会被调用。
如果没有定义,那么Python会迭代容器中的元素来一个一个比较,从而决定返回True或者False。
- 1
- 2
- 3
__missing__(self, key)
dict字典类型会有该方法,它定义了key如果在容器中找不到时触发的行为。
比如d = {'a': 1}, 当你执行d[notexist]时,d.__missing__('notexist')就会被调用。\
- 1
- 2
上下文管理器(实现了 __enter__和__exit__)
形如:
with open('1.txt', 'w') as file:
pass
- 1
- 2
- 3
__enter__
__enter__会返回一个值,并赋值给as关键词之后的变量。在这里,你可以定义代码段开始的一些操作。
- 1
- 2
__exit__
__exit__(self, exception_type, exception_value, traceback)
__exit__定义了代码段结束后的一些操作,可以这里执行一些清除操作,或者做一些代码段结束后需要立即执行的命令,比如文件的关闭,socket断开等。如果代码段成功结束,那么exception_type, exception_value, traceback 三个参数传进来时都将为None。如果代码段抛出异常,那么传进来的三个参数将分别为: 异常的类型,异常的值,异常的追踪栈。
如果__exit__返回True, 那么with声明下的代码段的一切异常将会被屏蔽。
如果__exit__返回None, 那么如果有异常,异常将正常抛出,这时候with的作用将不会显现出来。
- 1
- 2
- 3
- 4
- 5
对象的序列化
对象的反序列化操作必须要求序列化时, 有序列化时的类存在 比如 <__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() # 输出历史记录与上面一致
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
运算符
比较运算符
__eq__(self, other)
定义了比较操作符==的行为.
- 1
__ne__(self, other)
定义了比较操作符!=的行为.
- 1
__lt__(self, other)
定义了比较操作符<的行为.
- 1
__gt__(self, other)
定义了比较操作符>的行为.
- 1
__le__(self, other)
定义了比较操作符<=的行为.
- 1
__ge__(self, other)
定义了比较操作符>=的行为.
- 1
一元运算符
__pos__(self)
实现了'+'号一元运算符(比如+some_object)
- 1
__neg__(self)
实现了'-'号一元运算符(比如-some_object)
- 1
link
## 魔法属性
__dict__
类的__dict__属性存储了类定义的所有类属性、类方法等组成的键值对,但不包括继承而来的属性和方法
实例的__dict__属性存储了所有的实例属性的键值对,如果没有就为空;__init__方法其实就是对__dict__属性的初始化赋值;
- 1
- 2
- 3
__doc__
该属性记录了类的说明文档,用类和实例引用指向的都是类的__doc__属性,如果没有默认为None。
- 1
__module__
该属性记录类定义的位置,如果定义的位置正好是主程序,那么该值为"_main_",否则是类属于的模块的名字;
- 1
__class__
该属性指向该实例的类,即实例指向类对象,类对象指向元类;
- 1
__slots__
该属性起到限制动态绑定属性和方法的作用,该属性是一个元组,默认是不存在的,需要手动定义并且只对当前的类起作用,只有添加到元组中的名字才能被动态添加属性,否则报错!
- 1