当前位置:   article > 正文

Python3 : vars(self)的响应缺少属性_python vars self

python vars self

 

先讲一下应用场景:将实例对象全属性转换为json数据格式(定义了以下3个方法: to_json  、 to_json2、 to_dict)

分别应用了  vars(self) .keys() 和  self.__dict__.keys()

【问题描述】: vars(self)的响应时,有时会丢失实例的属性,没有返回实例属性对应的 字典key值;   self.__dict__.keys()也是一样;

【问题解决】:不知道原因,还没解决,收集相关资料如下


代码示例:

class BaseModel():

    @property
    def to_json(self):
        # import datetime
        # 获取对象所有的key
        keys = vars(self).keys()

        obj = {}
        for key in keys:
            if not key.startswith("_"):
                key = str(key)
                # 日期对象无法进行序列化,将日期对象转为字符串
                if isinstance(getattr(self, key), datetime):
                    obj[key] = getattr(self, key).strftime("%Y-%m-%d")
                elif isinstance(getattr(self, key), time):
                    obj[key] = getattr(self, key).strftime("%H:%M:%S")
                elif isinstance(getattr(self, key), date):
                    obj[key] = getattr(self, key).strftime("%Y-%m-%d")
                else:
                    obj[key] = getattr(self, key)
        return obj

    @property
    def to_json_2(self):
        # import datetime
        # 获取对象所有的key
        keys = vars(self).keys()

        obj = {}
        for key in keys:
            if not key.startswith("_"):
                key = str(key)
                # 日期对象无法进行序列化,将日期对象转为字符串
                if isinstance(getattr(self, key), datetime):
                    obj[key] = getattr(self, key).strftime("%Y-%m-%d %H:%M:%S")
                elif isinstance(getattr(self, key), time):
                    obj[key] = getattr(self, key).strftime("%H:%M:%S")
                elif isinstance(getattr(self, key), date):
                    obj[key] = getattr(self, key).strftime("%Y-%m-%d")
                else:
                    obj[key] = getattr(self, key)
        return obj

    # ------------------------------------------------------------------------------------------
    @property
    def to_dict(self):
        # import datetime
        # 获取对象所有的key
        keys = self.__dict__.keys()

        obj = {}
        for key in keys:
            if not key.startswith("_"):
                key = str(key)
                # 日期对象无法进行序列化,将日期对象转为字符串
                if isinstance(getattr(self, key), datetime):
                    obj[key] = getattr(self, key).strftime("%Y-%m-%d %H:%M:%S")
                elif isinstance(getattr(self, key), time):
                    obj[key] = getattr(self, key).strftime("%H:%M:%S")
                elif isinstance(getattr(self, key), date):
                    obj[key] = getattr(self, key).strftime("%Y-%m-%d")
                else:
                    obj[key] = getattr(self, key)
        return obj
    # ------------------------------------------------------------------------------------------

class Project(BaseModel, Base):
    """
    项目表
    """
    __tablename__ = "ds_project"
    project_id = Column(Integer, primary_key=True, autoincrement=True, unique=True, comment="项目ID")

    # 外键
    company_id = Column(Integer, nullable=True, comment="公司ID")
    department_id = Column(Integer, nullable=True, comment="部门ID")
    director_id = Column(Integer, nullable=True, comment="分管领导ID")
    pmo_id = Column(Integer, nullable=True, comment="PMO_ID")
    pm_id = Column(Integer, nullable=True, comment="项目经理ID")
    quality_assurance_id = Column(Integer, nullable=True, comment="QA_ID")
    project_name = Column(String(255), nullable=False, comment="项目名称")  # 唯一
    project_code = Column(String(120), nullable=True, unique=True, comment="项目编号")  # 唯一 自动生成(PM_产品英文名称首字母_年份_流水号)

    @classmethod
    @reconnect()
    def by_project_id(cls, is_all, project_id):
        if is_all:
            return dbSession.query(cls).filter_by(project_id=project_id).first()
        else:
            return dbSession.query(cls).filter_by(is_delete=False).filter_by(project_id=project_id).first()

<.... 略 ....>

查询某一个 Project 实例对象,并转为json

project_obj = Project.by_project_id(is_all=1, project_id=101)

project_obj.project_id   project_obj.project_name    等都有值

但是   project_obj.to_json  没有值

 


 

Python对象将它们的实例变量存储在属于对象的字典中。 vars(x)返回这个字典(和x .__ dict__一样)。另一方面,dir(x)返回x的“属性,它的类的属性,以及递归的类的基类的属性”的字典。

当你使用点运算符访问对象的属性时,python不仅仅是查找对象字典中的属性。一个常见的情况是当x是C类的对象,你调用方法m。

 

class C(object):
    def m(self):
        print "m"

x = C()
x.m()

方法m不存储在x .__ dict__中。它是类C的属性。
当你调用x.m(),python将开始寻找m在x .__ dict__,但它不会找到它。但是,它知道x是C的一个实例,所以它将在C .__ dict__中查找,找到它,并调用m作为第一个参数。

所以vars(x)和dir(x)之间的区别是,dir(x)在x的类(及其基础)中查找可以访问的属性的额外工作,而不仅仅是存储在x自己的符号表。在上面的例子中,vars(x)返回一个空字典,因为x没有实例变量。然而,dir(x)返回

 

['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',
'__hash__', '__init__', '__module__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'm']

 

 


 【原理解释】vars(self)的响应缺少属性

我已经定义了一个类,并且需要将其大多数属性移交给函数进行处理。因此,我认为与其创建一个巨大的混乱并命名它们,不如将其processSomething(vars(self))交给我,然后交出带有所有属性和值的漂亮字典。

但是我发现几乎所有的属性都缺失了。

我已停止调试器中的代码并进行了一些测试:

  1. <span style="color:#333333"><code>>>> vars(self).keys()
  2. dict_keys(['date_expire', 'tokenUrl', 'settings', 'requestSession', 'ttlDays'])</code></span>

这些是5。虽然我希望大约有20个属性,但根据__slots__我在这里的课程定义:

  1. <span style="color:#333333"><code>__slots__ = (
  2. 'token', # the invitation-token to load the username with
  3. 'request', # the http-request which is currently being serviced
  4. 'inhibit',
  5. #... many lines deleted
  6. 'templateObj', # an instance of myMail.template.Template
  7. 'emailBody', # what will be sent via SMTP
  8. 'warningsAr', # messages for the client
  9. )</code></span>

我可以在调试器窗口中看到属性,并且可以直接访问它们。我已经阅读了vars()手册,找不到任何开关。有趣的是,dir(self)显示所有属性名称,但不显示任何值。所以我不能使用它。但是我认为vars和dir应该显示相同吗?

我想我会建立一个解决方法,但我真的很想了解这里发生的事情。你能帮忙吗?

 

解决方案


vars()返回__dict__实例的名称空间。但是__slots__属性未存储在__dict__名称空间中。这就是他们的重点。

相反,Python在实例存储结构中为每个值创建专用的指针槽,并在类对象上使用描述符来检索这些值。因此inst.attr被翻译为type(inst).attr.__get__(inst)返回该值。

__slots__文档中

__slots__声明采用一系列实例变量,并且在每个实例中仅保留足够的空间来容纳每个变量的值。因为__dict__未为每个实例创建空间,所以节省了空间。

[...]

请注意,__dict__ 无论如何拥有一个通常是一个标志,您忘记使用子类__slots__的属性,或者您从不使用__slots__自身的基本Python类继承而来。正确使用会__slots__导致实例中没有__dict__名称空间;他们的目标是通过避免字典所需的稀疏哈希表来减少内存(这会浪费空间)。

再次从文档中:

  • 从没有的类继承时,该类__slots____dict__属性将始终可访问,因此__slots__子类中的定义是没有意义的。

[...]

  • __slots__声明的动作仅限于定义它的类。结果,子类将具有一个,__dict__除非它们也定义__slots__(该子类只能包含任何其他插槽的名称)。

如果要列出所有可用的实例字段,则必须包括__slots__该类的枚举,而不仅仅是看vars()

  1. <span style="color:#333333"><code>from itertools import chain
  2. def slots_for_instance(inst):
  3. def _slots_for_class(c):
  4. slots = getattr(c, '__slots__', ())
  5. if isinstance(slots, str):
  6. # __slots__ can be a string naming a single attribute
  7. slots = (slots,)
  8. return set(chain.from_iterable(
  9. getattr(_slots_for_class(c) for c in type(inst).__mro__))</code></span>

 

 


vars()等价于.__ dict __

#vars()
#说明:返回对象object的属性和属性值的字典对象
‘’’
vars(…)
vars([object]) -> dictionary
dictionary:字典对象
Without arguments, equivalent to locals().
With an argument, equivalent to object.dict.

  1. class My():
  2. 'Test'
  3. def __init__(self,name):
  4. self.name=name
  5. def test(self):
  6. print self.name
  7. vars(My)#返回一个字典对象,他的功能其实和 My.__dict__ 很像
  8. '''

vars()等价于.__ dict __

  1. vars(My)
  2. Out[11]:
  3. mappingproxy({'__dict__': <attribute '__dict__' of 'My' objects>,
  4. '__doc__': 'Test',
  5. '__init__': <function __main__.My.__init__>,
  6. '__module__': '__main__',
  7. '__weakref__': <attribute '__weakref__' of 'My' objects>,
  8. 'test': <function __main__.My.test>})
  9. My.__dict__
  10. Out[12]:
  11. mappingproxy({'__dict__': <attribute '__dict__' of 'My' objects>,
  12. '__doc__': 'Test',
  13. '__init__': <function __main__.My.__init__>,
  14. '__module__': '__main__',
  15. '__weakref__': <attribute '__weakref__' of 'My' objects>,
  16. 'test': <function __main__.My.test>})

循环按照key value输出

  1. for key,value in vars(My).items():
  2. print (key,':',value)
  3. '''
  4. test : <function test at 0x02112C70>----test函数
  5. __module__ : __main__
  6. __doc__ : Test
  7. __init__ : <function __init__ at 0x01E42B70>----构造函数

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/389913
推荐阅读
相关标签
  

闽ICP备14008679号