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)

posted @ 2020-07-03 16:43  _Biko  阅读(101)  评论(0编辑  收藏  举报