Python使用描述符实现属性类型检查的案例解析

 

1、如何使用描述符对实例属性做类型检查?

实际案例:

在某项目中,我们实现了一些类,并希望能像静态类型语言那样(C,C++,Java)对它们的实例属性做类型检查。

p = Person()
  p.name = 'Bob'	# 名字属性必须是str
  p.age = 18	        # 年龄必须是int
  p.height = 1.83	# 身高必须是float

要求:(1)可以对实例变量名指定类型

(2)赋予不正确类型时抛出异常

解决方案:

使用描述符来实现需要类型检查的属性:分别实现__get__, __set__,__delete__方法,在__set__内使用isinstance函数做类型检查。

拓展:静态类型语言变量只能引用一种确定类型的对象并且不能改变。类型检查是由编译器在编译阶段完成的,对于Python动态类型语言来讲一个变量可以引用任意类型的对象并且可以实时发生改变,也就是解释器不能完成类型检查,只能自己去实现。

什么是描述符?描述符就是包含__get__, __set__,__delete__这样方法的类,这三个方法只要包含其中一个那它就是描述符。

实例属性就是在一个类中将另一个类的实例作为该类的一个数属性。

 

2、代码演示

(1)描述符定义和访问流程介绍

class Descriptor(object):
  def __get__(self, instance, cls):
      # instance用于区分使用类访问x,还是使用实例访问x
      print('in __get__', instance, cls)
      return instance.__dict__['x']
  def __set__(self, instance, value):
      # 在set中对于类型进行检查
      print('in __set__')
      instance.__dict__['x'] = value
  def __delete__(self, instance):
      print('in __del__')
class A(object):
  # 在类中定义一个类属性x
  x = Descriptor()
a = A()
# 会被Descriptor的__get__方法所截获
print(a.x)
# 直接使用类A访问类属性,instance会被传入None
print(A.x)
# 会被Descriptor的__set__方法所截获
a.x = 5
# 会被Descriptor的__del__方法所截获
del a.x
'''
通常来说在描述符这些方法当中访问的是instance.__dict__这个字典,
也就是对于它的真正属性进行操作。
'''
a = A()
a.x = 5
print(a.__dict__)

(2)实现使用描述符检查实例属性类型

class Attr(object):
  def __init__(self, name, type_):
      self.name = name
      self.type_ = type_
  def __get__(self, instance, cls):
      return instance.__dict__[self.name]
  def __set__(self, instance, value):
      # 对字段类型做检测
      if not isinstance(value, self.type_):
          raise TypeError('expected an %s' % self.type_)
      instance.__dict__[self.name] = value
  def __delete__(self, instance):
      del instance.__dict__[self.name]
class Person(object):
  # 定义一个name字段,申请描述符实例
  name = Attr('name', str)
  age = Attr('age', int)
  height = Attr('height', float)
p = Person()
p.name = 'Bob'
print(p.name)
# age赋值字符串类型抛出异常错误
# p.age = '17'

关于Python使用描述符实现属性类型检查的文章就介绍至此,更多相关python属性类型检查内容请搜索编程宝库以前的文章,希望以后支持编程宝库

 求N的阶乘本题要求编写程序,计算N的阶乘。输入格式:输入在一行中给出一个正整数 N。输出格式:在一行中按照“product = F”的格式输出阶乘的值F,请注意等号的左右各有 ...