1

Python菜鸟在这里,

目前我正在使用 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

这是 in /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 梯子,如果添加了任何不在 User 对象中的键,那将失败。像:

for attribute in kwargs.keys():
    if attribute in User:
        setattr(user, attribute, kwargs[attribute])
    else:
        raise Exception("blah")

这样我就可以把它放在它自己的函数中(除非希望已经存在?)所以我不必一次又一次地做 if 梯子,所以我可以在不修改此代码的情况下更改表结构。

有什么建议么?

4

3 回答 3

2

我的建议是不要进一步简化它。如果您分配任意属性,您可能会踩到重要的对象结构。

我要做的一个简化是.keys()当你在字典上使用它时放弃;包含检查和迭代都已经使用了这些键。

...

再三考虑,您可以拥有一个包含已知安全属性的类属性,然后在函数中检查此属性,并setattr()在实例上使用。

于 2010-05-28T04:10:51.783 回答
2

实际上,声明性基类已经插入了您正在寻找的确切构造函数,如声明性模块文档中所述。所以只要做User(username="Carson", password="1234")就会做你想做的事,并User(something_not_an_attribute='foo')会引发异常。

于 2010-05-28T06:48:20.500 回答
1

如果您不需要覆盖继承的属性,

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 不能在创建的实例中设置为参数;这可不是什么好事……!-)

于 2010-05-28T04:30:19.240 回答