Python IsInstance() 用于类和子类

Posted

技术标签:

【中文标题】Python IsInstance() 用于类和子类【英文标题】:Python IsInstance() for classes and subclasses 【发布时间】:2018-10-27 03:31:03 【问题描述】:

此代码来自类章节第 8.13 节的 python 烹饪书第 3 版。该程序尝试定义各种数据结构,但希望对允许分配给某些属性的值施加约束。 我正在使用 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_attributesplace=SizedString('tester',size=8) 调试以下代码时,以下 if 条件为 True,而对于 name=String 和 share=Integer,else 条件为 True。

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

问题:

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

      setattr(cls, key, value(key))中的value(key)是什么意思,看不懂value(key)是什么意思?

对于冗长的上下文感到抱歉,但希望尽可能清楚。

【问题讨论】:

为什么你在SizedString('tester', size=8) 中传递那个虚拟的'tester' 值而不是仅仅使用SizedString(size=8)?或者,如果您出于某种原因想要强制执行将被 @check_attributes 覆盖的临时名称,为什么要允许 name=None 标题呼唤issubclass 【参考方案1】:

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

    我们必须仔细查看传递给check_attributes 函数的内容。仔细看看 nameshare 关键字参数的值是什么:

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

    注意到StringInteger 类名后面没有括号了吗?这意味着StringInteger 类对象本身 被传递到check_attributes,而不是任何一个类的实例。而且由于String 类对象和Integer 类对象不是Descriptor 的子类,isinstance(value, Descriptor) 失败。

    setattr(cls, key, value(key))中的value(key)是什么意思,看不懂value(key)是什么意思?

    考虑一下。由于value 具有传递给check_attributes 的任何关键字参数的值,并且该值不是Descriptor 类的实例,因此value 必须引用一个类对象。 (如果您不明白为什么会这样,请参考我对您第一个问题的回答)。所以调用value(key) 是创建某个类的实例,并将key 值作为构造函数参数传入。

【讨论】:

这些解释帮助了我。 很高兴我能帮上忙@Joe_12345!

以上是关于Python IsInstance() 用于类和子类的主要内容,如果未能解决你的问题,请参考以下文章

python isinstance函数(21)

类和对象的一些BIF

类和对象的一些BIF

python isinstance和issubclass区别

用于Wordpress的菜单和子菜单PHP

python issubclass 和 isinstance函数