[英]Setting attributes of a class during construction from **kwargs
Python noob在这里,
目前,我正在使用SQLAlchemy,我有这个:
from __init__ import Base
from sqlalchemy.schema import Column, ForeignKey
from sqlalchemy.types import Integer, String
from sqlalchemy.orm import relationship
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
username = Column(String, unique=True)
email = Column(String)
password = Column(String)
salt = Column(String)
openids = relationship("OpenID", backref="users")
User.__table__.create(checkfirst=True)
#snip definition of OpenID class
def create(**kwargs):
user = User()
if "username" in kwargs.keys():
user.username = kwargs['username']
if "email" in kwargs.keys():
user.username = kwargs['email']
if "password" in kwargs.keys():
user.password = kwargs['password']
return user
这是在/db/users.py
,因此它的用法如下:
from db import users
new_user = users.create(username="Carson", password="1234")
new_user.email = "email@address.com"
users.add(new_user) #this function obviously not defined yet
但是create()
的代码有点愚蠢,我想知道是否有更好的方法不需要if阶梯,并且如果添加了用户中没有的任何键,那将失败对象已经。 喜欢:
for attribute in kwargs.keys():
if attribute in User:
setattr(user, attribute, kwargs[attribute])
else:
raise Exception("blah")
这样,我就可以将其放入自己的函数中(除非希望已经存在?)因此,我不必一次又一次地执行if阶梯,因此可以在不修改此代码的情况下更改表结构。
有什么建议么?
我的建议是不要进一步简化它。 如果您分配任意属性,则有可能踩踏重要的对象结构。
我要做的一个简化就是在字典上使用.keys()
时删除它。 包含检查和迭代都已经使用了密钥。
...
再次考虑,您可能拥有一个包含已知安全属性的类属性,然后在函数中检查该属性,并在实例上使用setattr()
。
实际上,声明性基类已经插入了您要查找的确切构造函数,如声明性模块docs中所述 。 因此,仅执行User(username="Carson", password="1234")
完成您想要的操作,而User(something_not_an_attribute='foo')
会引发异常。
如果您不需要涵盖继承的属性,
def create(**kwargs):
keys_ok = set(User.__dict__)
user = User()
for k in kwargs:
if k in keys_ok:
setattr(user, k, kwargs[k])
如果确实需要覆盖继承的属性, 那么inspect.getmembers可以提供帮助(使用自定义谓词来避免名称以下划线开头的成员,或者您要确保无法以这种方式设置的其他成员)。
如果set(kwargs) - set(keys_ok)
不为空,我也将考虑(至少)发出警告-即,如果传递给create
某些命名参数不能设置为创建实例中的参数; 那不是一件好事...!-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.