前言
鄙人有次在使用SQLALchemy
的时候,对查询出来的对象,进行获取/重新赋值产生了点小问题
下面来一起看看这个小问题:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.dialects.mysql import TINYINT, INTEGER, VARCHAR, TEXT, DATE, DATETIME
from sqlalchemy import create_engine, Column
uri = "mysql+pymysql://root:@127.0.0.1:3306/test?charset=utf8mb4"
Base = declarative_base()
engine = create_engine(uri, pool_pre_ping=True, echo=True)
Session = sessionmaker(bind=engine)
Base = declarative_base()
session = Session()
class Student(Base):
__tablename__ = "tStudent"
id = Column(INTEGER, autoincrement=True, primary_key=True)
nValid = Column(INTEGER, comment="1-有效;2- 无效", nullable=False, default=1)
sName = Column(VARCHAR(100), comment="学生姓名", nullable=False)
nAge = Column(INTEGER, comment="年龄")
sCnDesc = Column(TEXT)
sEnDesc = Column(TEXT)
student_a = Student()
student_a.id = 23
student_a.nValid = 1
student_a.sName = "James"
student_a.nAge = 35
student_a.sCnDesc = "大家好,我叫詹姆斯!"
student_a.sEnDesc = "Hello everyone, My name is James!"
session.add(student)
session.commit()
鄙人开发中遇到一个这样的使用:
当我通过sqlalchemy
查询数据,而且是使用.all()
来查询的时候,
返回的是一个list
,且里面的每一个元素都是一个Object
;
而此时我想要预先设置好一个list/set来存这些字段,
然后获取的时候通过遍历来获取,心里想:这样不就是解决我的问题了吗,这能有多难?
然后操作就是这样写:1
2
3
4
5
6res = session.query(Student).all()
# 比如,要获取属性id、sName、nAge:
keys = ["id", "sName", "nAge"]
for one in res:
for k in keys:
print(f"属性:{k} 对应的值为:{one.k}")
现在请你们来猜测一下这个使用对不对?或者输出结果是什么?你们先想一下结果再往下看…
此时运行将会得到下面的错误,是不是很惊喜?嗯哼?啥玩意啊?1
2
3
4Traceback (most recent call last):
File "E:/projects/python/daily/temp.py", line 208, in <module>
print(f"属性:{k} 对应的值为:{one.k}")
AttributeError: 'Student' object has no attribute 'k'
看了一下,没有属性 k
,这student对象的确没有属性 k
啊,我的天,那我得怎么用?
然后这时候如果你使用 getattr
的话,这就很容易解决你这种需求,下面来分析一下源码:
这两个作为Python的内置属性,下面来分析一下源码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18def getattr(object, name, default=None): # known special case of getattr
"""
getattr(object, name[, default]) -> value
Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
"""
pass
def setattr(x, y, v): # real signature unknown; restored from __doc__
"""
Sets the named attribute on the given object to the specified value.
setattr(x, 'y', v) is equivalent to ``x.y = v''
"""
pass
从上面的源码可以分析出来 getattr
就是从一个对象从获取你想要的属性,使用格式是:
- [x]
getattr(对象, 你要获取的属性)
那么我这个例子里面的用法就是:1
2
3
4
5
6
7
8
9
10
11
12res = session.query(Student).all()
# 比如,要获取属性id、sName、nAge:
keys = ["id", "sName", "nAge"]
for one in res:
for k in keys:
# one.k 改为 getattr(one, k) 即可获取对应的属性
print(f"属性:{k} 对应的值为:{getattr(one, k)}")
>>>
属性:id 对应的值为:23
属性:sName 对应的值为:James
属性:nAge 对应的值为:35
- [x]
setattr
的使用格式是:setattr(对象, 需要设置的属性, 设置的内容)
请看下面栗子:
1 | res = session.query(Student).all() |
可以再次通过上面的getattr
使用来查询一遍数据库,即可验证刚刚的用法对不对
==同时,官方还指出:setattr(x, 'y', v)
是等价于x.y = v
,笔者通过分析,这个用法其实也可以对这个x
对象进行添加另外一个新的属性y
==
下面这个例子是给对象增加一个school
属性:
1 | setattr(student_a, "school", "Beijing University") |
小教程有用的话,点个赞吧
谢谢大家,我系渣渣辉
EOF