• Scrapy Item类分析


    class BookItem(Item):
        name=Field()
        price=Field()
    book=BookItem(name='abc',price=43)

    在这里BookItem 继承Item类,并且有2个类属性:name和price。都是类Field的实例。

    @six.add_metaclass(ItemMeta)
    class Item(DictItem):
        pass

    这里表示Item继承于DictItem。并且使用元类ItemMeta创建Item这个类实例。

    class ItemMeta(ABCMeta):
    
        def __new__(mcs, class_name, bases, attrs):
            classcell = attrs.pop('__classcell__', None)
            new_bases = tuple(base._class for base in bases if hasattr(base, '_class'))
            _class = super(ItemMeta, mcs).__new__(mcs, 'x_' + class_name, new_bases, attrs)
    
            fields = getattr(_class, 'fields', {})
            new_attrs = {}
            for n in dir(_class):
                v = getattr(_class, n)
                if isinstance(v, Field):
                    fields[n] = v
                elif n in attrs:
                    new_attrs[n] = attrs[n]
    
            new_attrs['fields'] = fields
            new_attrs['_class'] = _class
            if classcell is not None:
                new_attrs['__classcell__'] = classcell
            return super(ItemMeta, mcs).__new__(mcs, class_name, bases, new_attrs)

    在这里__new__的参数传入分别是(ItemMeta,BookItem,Item,( ('name',{}),('price',()) ))    PS:可参考 www.cnblogs.com/solakevon/p/8894822.html

    因为在使用元类创建类实例时,会把类名,父类名,类属性传入。和使用type创建类实例一样。

    new_bases是个空元祖。_class是x_item类。类属性和BookItem一样.

    在for循环里面会把在attrs里面Field的实例给传到fields这个字典里面。其他非Field实例的类属性都放到new_attrs里面

    最后把fields这个字典也放到new_attrs里面。此时fields里面有name和price。

    class DictItem(MutableMapping, BaseItem):
    
        fields = {}
    
        def __init__(self, *args, **kwargs):
            self._values = {}
            if args or kwargs:  # avoid creating dict for most common case
                for k, v in six.iteritems(dict(*args, **kwargs)):
                    self[k] = v
    
        def __getitem__(self, key):
            return self._values[key]
    
        def __setitem__(self, key, value):
            if key in self.fields:
                self._values[key] = value
            else:
                raise KeyError("%s does not support field: %s" %
                    (self.__class__.__name__, key))
    
        def __delitem__(self, key):
            del self._values[key]
    
        def __getattr__(self, name):
            if name in self.fields:
                raise AttributeError("Use item[%r] to get field value" % name)
            raise AttributeError(name)
    
        def __setattr__(self, name, value):
            if not name.startswith('_'):
                raise AttributeError("Use item[%r] = %r to set field value" %
                    (name, value))
            super(DictItem, self).__setattr__(name, value)
    
        def __len__(self):
            return len(self._values)
    
        def __iter__(self):
            return iter(self._values)
    
        __hash__ = BaseItem.__hash__
    
        def keys(self):
            return self._values.keys()
    
        def __repr__(self):
            return pformat(dict(self))
    
        def copy(self):
            return self.__class__(self)

    在DictItem将会实现Item对象的一些功能。

  • 相关阅读:
    git 还原某个文件~~~
    uniqid()
    array_filter 过滤一维中空数组,数组的序列不变
    加密 解密
    gitlab基本维护和使用
    vim 单文件中查找方法
    php数组定义
    $('.goods_tag_ids_all')[0].checked = true;//~~~~~ 单条改变checkbox 属性样式
    由买冰箱想到的
    2014年年终总结
  • 原文地址:https://www.cnblogs.com/solakevon/p/8894689.html
Copyright © 2020-2023  润新知