Python IsInstance() 用于类和子类

4

这段代码来自于《Python Cook Book 3rd Edition》中的类章节第8.13节。该程序试图定义各种数据结构,但希望对允许分配给某些属性的值强制执行约束条件。 我正在使用Pycharm IDE在Python 2.7中执行该程序。

# Base class. Uses a descriptor to set a value
class Descriptor(object):
    def __init__(self, name=None, **opts):
        self.name = name
        for key, value in opts.items():
            setattr(self, key, value)

    def __set__(self, instance, value):
        instance.__dict__[self.name] = value

# Descriptor for enforcing types
class Typed(Descriptor):
    expected_type = type(None)
    def __set__(self, instance, value):
        if not isinstance(value, self.expected_type):
            raise TypeError('expected ' + str(self.expected_type))
        super(Typed,self).__set__(instance, value)

class Integer(Typed):
    expected_type = int

class String(Typed):
    expected_type = str

class MaxSized(Descriptor):
    def __init__(self, name=None, **opts):
        if 'size' not in opts:
            raise TypeError('missing size option')
        super(MaxSized,self).__init__(name, **opts)

    def __set__(self, instance, value):
        if len(value) >= self.size:
            raise ValueError('size must be < ' + str(self.size))
        super(MaxSized,self).__set__(instance, value)


class SizedString(String, MaxSized):
    pass

# Class decorator to apply constraints
def check_attributes(**kwargs):
    def decorate(cls):
        for key, value in kwargs.items():
            if isinstance(value, Descriptor):
                value.name = key
                setattr(cls, key, value)
            else:
                setattr(cls, key, value(key))
        return cls
    return decorate

# Example
@check_attributes(name=String,shares=Integer,place=SizedString('tester',size=8))
class Stock(object):
    def __init__(self, stkname, stkqty,stkhq):
        self.name = stkname
        self.shares = stkqty
        self.place = stkhq

执行以下初始化代码时,
s = Stock('ACME', 50,'hky')
print s.name # print ACME
print s.shares # prints 50
print s.place # prints hky

条件:

当调试下面的代码 @check_attributes place=SizedString('tester',size=8) 时,下面的if条件为True,而对于name=String and shares=Integer,则else条件为True。

       if isinstance(value, Descriptor):
            value.name = key
            setattr(cls, key, value)
        else:
            setattr(cls, key, value(key))

问题:

  1. 如果SizedString是Descriptor的一个实例(基于继承层次结构-String,Typed,MaxSized,Descriptor),那么String和Integer也应该满足If条件,对吗?因为最终它们也是(typed, Descriptor)的子类?

    1. 在setattr(cls,key,value(key))中,value(key)是什么意思,无法理解value(key)的含义?

抱歉内容有点长,但希望尽可能清晰明了。


为什么在 SizedString('tester', size=8) 中传递虚拟的 'tester' 值,而不是直接使用 SizedString(size=8)?或者,如果您出于某种原因想要强制使用仅将被 @check_attributes 覆盖的临时名称,为什么允许 name=None - abarnert
标题正在呼唤 issubclass - Dan D.
1个回答

2
  1. If SizedString is an instance of Descriptor ( based on Inheritance hierarchy- String , Typed , MaxSized, Descriptor ), then String and Integer also should satisfy the If condition right ? because at the end it is also the subclass of ( typed , Descriptor ) ?

    We have to look carefully at what is being passed into the check_attributes function. Look closer at what the value of the name and share keyword arguments are:

    @check_attributes(name=String,shares=Integer,place=SizedString('tester',size=8))
    

    Notice the lack of parenthesis after the String and Integer class names? This means the String and Integer class object themselves are being passed into check_attributes, not an instance of either class. And since the String class object and the Integer class object are not sub-classes of Descriptor, isinstance(value, Descriptor) fails.

  2. What is value(key) in setattr(cls, key, value(key)) means , cant understand what is value(key ) means ?

    Think about it. Since value has the value of whatever keyword argument was passed into check_attributes, and the value is not an instance of the Descriptor class, then value must be referring to a class object. (If you don't understand why this is, refer back to my answer to your first question). So calling value(key) is creating an instance of some class, and passing in the key value as a constructor argument.


这些解释对我很有帮助。 - Joe_12345
很高兴能帮助@Joe_12345! - Christian Dean

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接