赞
踩
先讲一下应用场景:将实例对象全属性转换为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']
我已经定义了一个类,并且需要将其大多数属性移交给函数进行处理。因此,我认为与其创建一个巨大的混乱并命名它们,不如将其processSomething(vars(self))
交给我,然后交出带有所有属性和值的漂亮字典。
但是我发现几乎所有的属性都缺失了。
我已停止调试器中的代码并进行了一些测试:
- <span style="color:#333333"><code>>>> vars(self).keys()
- dict_keys(['date_expire', 'tokenUrl', 'settings', 'requestSession', 'ttlDays'])</code></span>
这些是5。虽然我希望大约有20个属性,但根据__slots__
我在这里的课程定义:
- <span style="color:#333333"><code>__slots__ = (
- 'token', # the invitation-token to load the username with
- 'request', # the http-request which is currently being serviced
- 'inhibit',
- #... many lines deleted
- 'templateObj', # an instance of myMail.template.Template
- 'emailBody', # what will be sent via SMTP
- 'warningsAr', # messages for the client
- )</code></span>
我可以在调试器窗口中看到属性,并且可以直接访问它们。我已经阅读了vars()的手册,找不到任何开关。有趣的是,dir(self)
显示所有属性名称,但不显示任何值。所以我不能使用它。但是我认为vars和dir应该显示相同吗?
我想我会建立一个解决方法,但我真的很想了解这里发生的事情。你能帮忙吗?
vars()
返回__dict__
实例的名称空间。但是__slots__
属性未存储在__dict__
名称空间中。这就是他们的重点。
相反,Python在实例存储结构中为每个值创建专用的指针槽,并在类对象上使用描述符来检索这些值。因此inst.attr
被翻译为type(inst).attr.__get__(inst)
返回该值。
该
__slots__
声明采用一系列实例变量,并且在每个实例中仅保留足够的空间来容纳每个变量的值。因为__dict__
未为每个实例创建空间,所以节省了空间。[...]
请注意,__dict__
无论如何拥有一个通常是一个标志,您忘记使用子类__slots__
的属性,或者您从不使用__slots__
自身的基本Python类继承而来。正确使用会__slots__
导致实例中没有__dict__
名称空间;他们的目标是通过避免字典所需的稀疏哈希表来减少内存(这会浪费空间)。
再次从文档中:
- 从没有的类继承时,该类
__slots__
的__dict__
属性将始终可访问,因此__slots__
子类中的定义是没有意义的。[...]
__slots__
声明的动作仅限于定义它的类。结果,子类将具有一个,__dict__
除非它们也定义__slots__
(该子类只能包含任何其他插槽的名称)。
如果要列出所有可用的实例字段,则必须包括__slots__
该类的枚举,而不仅仅是看vars()
:
- <span style="color:#333333"><code>from itertools import chain
-
- def slots_for_instance(inst):
- def _slots_for_class(c):
- slots = getattr(c, '__slots__', ())
- if isinstance(slots, str):
- # __slots__ can be a string naming a single attribute
- slots = (slots,)
- return set(chain.from_iterable(
- getattr(_slots_for_class(c) for c in type(inst).__mro__))</code></span>
#vars()
#说明:返回对象object的属性和属性值的字典对象
‘’’
vars(…)
vars([object]) -> dictionary
dictionary:字典对象
Without arguments, equivalent to locals().
With an argument, equivalent to object.dict.
- class My():
- 'Test'
- def __init__(self,name):
- self.name=name
-
- def test(self):
- print self.name
-
-
- vars(My)#返回一个字典对象,他的功能其实和 My.__dict__ 很像
-
-
- '''
vars()等价于.__ dict __
- vars(My)
- Out[11]:
- mappingproxy({'__dict__': <attribute '__dict__' of 'My' objects>,
- '__doc__': 'Test',
- '__init__': <function __main__.My.__init__>,
- '__module__': '__main__',
- '__weakref__': <attribute '__weakref__' of 'My' objects>,
- 'test': <function __main__.My.test>})
-
- My.__dict__
- Out[12]:
- mappingproxy({'__dict__': <attribute '__dict__' of 'My' objects>,
- '__doc__': 'Test',
- '__init__': <function __main__.My.__init__>,
- '__module__': '__main__',
- '__weakref__': <attribute '__weakref__' of 'My' objects>,
- 'test': <function __main__.My.test>})
循环按照key value输出
- for key,value in vars(My).items():
- print (key,':',value)
- '''
- test : <function test at 0x02112C70>----test函数
- __module__ : __main__
- __doc__ : Test
- __init__ : <function __init__ at 0x01E42B70>----构造函数
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。