Python基础及语法(十一)
目录
查看属性
dir()
__dir__
返回对象或类的所有成员名称列表
print(dir()) # ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__']
class A:
def __dir__(self):
return [1]
f = A()
print(dir()) # ['A', '__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'f']
print(f.__dir__()) # [1]
魔术方法
- 分类
- 创建,初始化和销毁
- 可视化
- hash
- bool
- 运算符重载
- 容器和大小
- 可调用对象
- 上下文管理
- 反射
- 描叙器
- 其它
创建,初始化和销毁
class Test:
def __new__(cls, x):
print('new', x)
return super().__new__(cls)
def __init__(self, x):
self.x = x
print('init', self.x)
def __del__(self):
print('del', self.x)
test = Test('test1')
print(Test('test2').x)
print(test.x)
# new test1
# init test1
# new test2
# init test2
# del test2
# test2
# test1
# del test1
可视化
class Test:
def __init__(self, x='a'):
self.x = x
def __str__(self):
return '{} {}'.format('str', self.x)
def __repr__(self):
return '{} {}'.format('repr', self.x)
def __bytes__(self):
import json
return json.dumps(self.__dict__).encode()
print(Test()) # str a
print([Test('b')]) # [repr b]
print(bytes(Test('c'))) # b'{"x": "c"}'
hash
class Test:
def __init__(self, x, y):
self.x = x
self.y = y
def __hash__(self): # 如果定义了eq方法没有定义hash方法,不能hash
return hash((self.x, self.y))
def __eq__(self, other): # 如果没有eq方法不能去重,返回{(4, 5), (4, 5), (3, 5)}
return (self.x, self.y) == (other.x, other.y)
def __repr__(self):
return '({}, {})'.format(self.x, self.y)
t1 = Test(4, 5)
t2 = Test(4, 5)
t3 = Test(3, 5)
print(hash(t1) is hash(t2)) # False
print(hash(t1) == hash(t2)) # True
print(hash(t1) == hash(t3)) # False
print({t1, t2, t3}) # {(4, 5), (3, 5)}
bool
class Test:
def __init__(self, x, y):
self.x = x
self.y = y
def __bool__(self):
return self.x == self.y
print(bool(Test(4, 5))) # False
print(bool(Test(5, 5))) # True
运算符重载
class Test:
def __init__(self, x):
self.x = x
def __repr__(self):
return '{}'.format(self.x)
def __lt__(self, other):
print('lt', end=' ')
return self.x < other.x
def __le__(self, other):
print('le', end=' ')
return self.x <= other.x
def __eq__(self, other):
print('eq', end=' ')
return self.x == other.x
def __gt__(self, other):
print('gt', end=' ')
return self.x > other.x
def __ge__(self, other):
print('ge', end=' ')
return self.x >= other.x
def __ne__(self, other):
print('ne', end=' ')
return self.x != other.x
def __add__(self, other):
print('add', end=' ')
return self.x + other.x
def __sub__(self, other):
print('sub', end=' ')
return self.x - other.x
def __mul__(self, other):
print('mul', end=' ')
return self.x * other.x
def __truediv__(self, other):
print('truediv', end=' ')
return self.x / other.x
def __mod__(self, other):
print('mod', end=' ')
return self.x % other.x
def __floordiv__(self, other):
print('floordiv', end=' ')
return self.x // other.x
def __pow__(self, other):
print('pow', end=' ')
return self.x ** other.x
def __divmod__(self, other):
print('divmod', end=' ')
return divmod(self.x, other.x)
def __iadd__(self, other):
print('iadd', end=' ')
self.x += other.x
return self
def __isub__(self, other):
print('isub', end=' ')
self.x -= other.x
return self
def __imul__(self, other):
print('imul', end=' ')
self.x *= other.x
return self
def __itruediv__(self, other):
print('itruediv', end=' ')
self.x /= other.x
return self
def __imod__(self, other):
print('imod', end=' ')
self.x %= other.x
return self
def __ifloordiv__(self, other):
print('ifloordiv', end=' ')
self.x //= other.x
return self
def __ipow__(self, other):
print('ipow', end=' ')
self.x **= other.x
return self
def __radd__(self, other):
print('radd', end=' ')
return other+self.x
def __rsub__(self, other):
print('rsub', end=' ')
return other-self.x
def __rtruediv__(self, other):
print('rtruediv', end=' ')
return other / self.x
def __rmul__(self, other):
print('rmul', end=' ')
return other * self.x
def __rmod__(self, other):
print('rmod', end=' ')
return other % self.x
def __rpow__(self, other):
print('rpow', end=' ')
return other ** self.x
def __rfloordiv__(self, other):
print('rfloordiv', end=' ')
return other // self.x
t1 = Test(4)
t2 = Test(5)
print(t1 < t2) # lt True
print(t1 <= t2) # le True
print(t1 > t2) # gt False
print(t1 >= t2) # ge False
print(t1 == t2) # eq False
print(t1 != t2) # ne True
print(t1+t2) # add 9
print(t1-t2) # sub -1
print(t1*t2) # mul 20
print(t1/t2) # truediv 0.8
print(t1 % t2) # mod 4
print(t1//t2) # floordiv 0
print(t1 ** t2) # pow 1024
print(divmod(t1, t2)) # divmod (0, 4)
t1 += t2
print(t1) # iadd 9
t1 -= t2
print(t1) # isub 4
t1 *= t2
print(t1) # imul 20
t1 /= t2
print(t1) # itruediv 4.0
t1 %= t2
print(t1) # imod 4.0
t1 **= t2
print(t1) # ipow 1024.0
t1 //= t2
print(t1) # ifloordiv 204.0
print(1+t1) # radd 205.0
print(1-t1) # rsub -203.0
print(1*t1) # rmul 204.0
print(408/t1) # rtruediv 2.0
print(1 % t1) # rmod 1.0
print(1000//t1) # rfloordiv 4.0
print(1 ** t1) # rpow 1.0
@functools.total_ordering装饰器
import functools
@functools.total_ordering # 在部分环境下可以减小代码量,但有可能带来性能的问题,通常不使用
class Test:
def __init__(self, x):
self.x = x
def __repr__(self):
return '{}'.format(self.x)
def __eq__(self, other):
print('eq', end=' ')
return self.x == other.x
def __gt__(self, other):
print('gt', end=' ')
return self.x > other.x
def __add__(self, other):
print('add', end=' ')
self.x += other.x
return self
def __sub__(self, other):
print('sub', end=' ')
self.x -= other.x
return self
def __mul__(self, other):
print('mul', end=' ')
self.x *= other.x
return self
def __truediv__(self, other):
print('truediv', end=' ')
self.x /= other.x
return self
def __mod__(self, other):
print('mod', end=' ')
self.x %= other.x
return self
def __floordiv__(self, other):
print('floordiv', end=' ')
self.x //= other.x
return self
def __pow__(self, other):
print('pow', end=' ')
self.x **= other.x
return self
t1 = Test(4)
t2 = Test(5)
print(t1 < t2) # gt eq True
print(t1 <= t2) # gt True
print(t1 > t2) # gt False
print(t1 >= t2) # gt eq False
print(t1 == t2) # eq False
print(t1 != t2) # eq True
print(t1+t2) # add 9
print(t1-t2) # sub 4
print(t1*t2) # mul 20
print(t1/t2) # truediv 4.0
print(t1 % t2) # mod 4.0
print(t1 ** t2) # pow 1024.0
print(t1//t2) # floordiv 204.0
t1 += t2
print(t1) # add 209.0
t1 -= t2
print(t1) # sub 204.0
t1 *= t2
print(t1) # mul 1020.0
t1 /= t2
print(t1) # truediv 204.0
t1 %= t2
print(t1) # mod 4.0
t1 **= t2
print(t1) # pow 1024.0
t1 //= t2
print(t1) # floordiv 204.0
容器和大小
class Test:
def __init__(self, x):
self.x = list(x)
def __len__(self):
print('len', end=' ')
return len(self.x)
def __iter__(self):
print('iter', end=' ')
return iter(self.x)
def __contains__(self, item):
print('contains', end=' ')
return item in self.x
def __getitem__(self, item):
print('getitem', end=' ')
return self.x[item]
def __setitem__(self, key, value):
print('setitem')
self.x[key] = value
class Dict(dict):
def __missing__(self, key):
print('missing', end=' ')
self[key] = key
return key
t1 = Test(range(1, 10, 2))
print(len(t1)) # len 5
print(3 in t1) # contains True
print(t1[-2]) # getitem 7
t1[2] = 11 # setitem
print(list(iter(t1))) # iter [1, 3, 11, 7, 9]
t2 = Dict()
print(t2['a']) # missing a
print(t2['a']) # a
可调用对象
class Test:
def __init__(self, x):
self.x = x
def __call__(self, *args, **kwargs):
print('call', end=' ')
return '{}'.format(self.x)
t1 = Test(4)
print(t1()) # call 4
上下文管理
为代码执行前和执行后提供代码补充,代码有误也会执行结束后的代码,自动优化关闭资源
class Test:
def __init__(self):
print('init')
def __enter__(self):
print('enter')
def __exit__(self, exc_type, exc_val, exc_tb):
print('exit')
print(exc_type) # 返回错误类型
print(exc_val) # 返回错误提示
print(exc_tb) # 返回错误对象
t1 = Test() # init
with t1 as f: # enter
pass # exit None None None
@contextlib.contextmanager装饰器
import contextlib
@contextlib.contextmanager # 装饰器实现上下文管理
def test():
print('enter')
yield
print('exit')
with test() as f: # enter
pass # exit
反射
class Test:
n = 0
def __init__(self, x):
self.x = x
def __getattr__(self, item):
print('getattr', item, end=' ')
def __setattr__(self, key, value):
print('setattr', key, value)
def __delattr__(self, item):
print('delattr', item)
def __getattribute__(self, item):
print('getattribute', item, end=' ')
return super().__getattribute__(item)
test = Test(4) # setattr x 4
print(test.n) # getattribute n 0
print(test.x) # getattribute x getattr x None
del test.x # delattr x
描叙器
class A:
def __init__(self):
self.a = 'a'
print('A.init')
def __get__(self, instance, owner):
print('A.get', instance, owner, end=' ')
return self
def __set__(self, instance, value):
print('A.set', instance, value)
self.data = value
def __delete__(self, instance):
print('A.delete', instance)
def __set_name__(self, owner, name):
print('set_name', owner, name)
self.name = name
class B:
x = A() # A.init
def __init__(self):
print('B.init', end=' ')
self.x = 'B.x'
print(B.x) # A.get None <class '__main__.B'> <__main__.A object at 0x0000022DFFE65320>
print(B.x.a) # A.get None <class '__main__.B'> a
print(B().x) # set_name <class '__main__.B'> x
test = B() # B.init A.set <__main__.B object at 0x0000022D80FC5588> B.x
print(test.x) # A.get <__main__.B object at 0x0000022D80FC5588> <class '__main__.B'> <__main__.A object at 0x0000022DFFE65320>
print(test.x.a) # A.get <__main__.B object at 0x0000022D80FC5588> <class '__main__.B'> a
print(test.x.data) # A.get <__main__.B object at 0x0000022D80FC5588> <class '__main__.B'> B.x
del test.x # A.delete <__main__.B object at 0x0000022D80FC5588>
Python中的描叙器
class Test:
@classmethod # 非数据描叙器
def x(cls):
return 1
@staticmethod # 非数据描叙器
def y(self):
return self
@property # 数据描叙器
def z(self):
return 5
def get(self):
return self.x
def __init__(self):
self.x = 3
self.y = 4
def add(x, y):
return x+y
print(Test.x()) # 1
print(Test.y(2)) # 2
test = Test()
print(test.x, test.y, test.z) # 3 4 5
try:
test.z = 55
except AttributeError as e:
print(e) # can't set attribute
__slots__方法
class A:
__slots__ = ('x', 'y') # 定义__slots__方法后取消类字典,不能定义__slots__元组外的其它属性,可节省空间
def __init__(self,x, y):
self.x = x
self.y = y
a = A(1, 2)
print(a.x, a.y) # 1 2
a.x = 3
print(a.x) # 3
a.z = 4 # AttributeError
tracemalloc模块
import tracemalloc # 统计内存使用情况
tracemalloc.start()
ls = [zip('ab', (0, 1)) for j in range(1000000)] # size=298 MiB, count=5000001, average=63 B
d = [dict(zip('ab', (0, 1))) for i in range(1000000)] # size=237 MiB, count=1999962, average=124 B
t = [tuple(zip('ab', (0, 1))) for k in range(1000000)] # size=191 MiB, count=3000005, average=67 B
snapshot = tracemalloc.take_snapshot()
statistics = snapshot.statistics('lineno')
for i in statistics:
print(i)