python编程高级篇(二)

内容简介

这篇文章还是围绕类属性魔法方法装饰器进行展开学习的。

涉及的类属性:
__slots__
其值为类初始化时用到的参数名列表或元组,主要用于设置(关闭或者限制)类的动态绑定属性,一旦设置了该属性,则类实例化之后,不可再 动态添加其他没有在该属性中声明的变量

魔法方法

__new__ # 注意:在类实例化时,该方法比__init__先执行,并且必须返回类(return super().__new__(cls))
__enter__
__exit__
__lt__
__eq__
__gt__
__getattr__
__getattribute__
__get__
__set__
__delete__

装饰器

from functools import total_ordering
import contextlib

@total_ordering
class compare():
	def __init__(self, a):
        pass

@contextlib.contextmanager
def file_open(file):
    pass

with上下文

对于一个类或者方法,要想支持with语句,需要在类中实现魔法方法:

__enter__
__exit__

代码实例:

class Sample(object):
    def __init__(self):
        print('init')
    def __enter__(self):
        print('start')
        return self # 注意:必须返回self 给后面的程序调用
    def demo(self):
        print('this is demo')
    def __exit__(self, exc_type, exc_val, exc_tb):
        # 异常类
        print(exc_type, '1')
        # 异常值
        print(exc_val, '2')
        # traceback
        print(exc_tb, '3')
        print('end')


with Sample() as sample:
    sample.demo()

也可以使用上下文装饰器简化上述过程。

import contextlib

@contextlib.contextmanager
def demo():
    print('this is demo')
    yield '' # 必须为迭代器 或者 生成器
    print('end')


with demo() as sample:
    print('ok')

类实例动态绑定变量

就是在类 实例化之后,对实例进行任意属性的绑定,例如:

import sys

class x():
    def __init__(self):
        print('123')

>>> aa=x()
123
>>> sys.getsizeof(aa) # 查看实例 aa 所占内存大小
56
>>> aa.xx=12345 # 任意绑定属性名xx,属性值12345
>>> print(aa.xx)
12345
>>> sys.getsizeof(aa.xx) # 查看新增属性xx所占内存大小
28

为了避免动态绑定属性带来的内存浪费,需要引入类属性:“__slots__”

import sys

class x():
    __slots__ = ["id"]
    def __init__(self, id):
        print('123')
        print(id)

aa = x('user1')
>>> aa.s=1 # 设置 __slots__ 之外的属性时,报错
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'x' object has no attribute 's'
>>> aa.id=1
>>> print(aa.id)
1

类实例的比较

对于一个类实例,如果要想支持大小比较:
<, =, > ,>= ,<=
则需要分别实现魔法方法

__lt__
__eq__
__gt__
__ge__
__le__

但是也可以借助装饰器简化,只需实现 其中的两个:
__eq__ 和 __lt__ 或者 __eq__ 和 __gt__
代码实现:

from functools import total_ordering

@total_ordering
class cmpares():
    def __init__(self, value):
        self.value = value
    def __eq__(self, other):
        return self.value == other.value
    def __lt__(self, other):
        return self.value < other.value

a = cmpares(12)
b = cmpares(6)
>>> print(a > b)
True
>>> print(a == b)
False
>>> print(a < b)
False
>>> print(a <= b)
False
>>> print(a >= b)
True

实例属性查找

此处涉及的魔法方法为:

__getattr__
__getattribute__

其中 __getattribute__的优先级比 __getattr__高,所以前者先执行,当调用实例的属性不存在时,后者会被调用。
代码实例:

class xx():
    def __init__(self, name, age, attrs = {}):
        self.name = name
        self.age = age
        self.attrs = attrs
    def __getattr__(self,item):
        return self.attrs.get(item, 'not exists.')

a=xx('li',9)
print(a.b) # 属性不存在,返回 'not exists.'

属性描述符

涉及的方法:

__get__
__set__
__delete__

上述方法主要使属性的获取和设置便于批量操作,适用于数据描述符(至少实现前两个方法)和非数据描述符(只实现__get__方法)。
代码实例:

class Inld(object):
    def __get__(self, instance, owner):
        print('get')
        return self.values
    def __set__(self, instance, value):
        print('set')
        self.values = value
    def __delete__(self, instance):
        pass

class ts:
    age = Inld() #类属性

a = ts()
a.age = 88
print(a.age)

属性查找顺序(优先级依次降低):
数据描述符 > 实例__dict__ > 类(基类)__dict__ ( 非数据描述符 > __dict__)

type创建类

type不只是用于查看对象类型,还可以动态创建类。

def get_age(self):
    print(111)

User = type("User", (), {'name': 'test111', 'method1': get_age})
user = User()
print(user)
print(user.name)
user.method1()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值