Python 在从**kwargs构建期间设置类的属性

Python 在从**kwargs构建期间设置类的属性,python,class,sqlalchemy,class-attributes,Python,Class,Sqlalchemy,Class Attributes,这里是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"

这里是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梯形图,如果添加了任何不在User对象中的键,那么该方法就会失败。比如:

for attribute in kwargs.keys():
    if attribute in User:
        setattr(user, attribute, kwargs[attribute])
    else:
        raise Exception("blah")
这样我就可以把它放在它自己的函数中,除非它已经存在了?因此,我不必一次又一次地执行if梯形图,因此我可以在不修改此代码的情况下更改表结构


有什么建议吗?

我的建议是不要再简化了。如果指定任意属性,则可能会踩到重要的对象结构

我要做的一个简化就是当你在dict上使用它时,去掉.keys;包含检查和迭代都已经使用了这些键


再想一想,您可以拥有一个包含已知安全属性的class属性,然后在函数中检查该属性,并在实例上使用setattr。

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

我要做的一个简化就是当你在dict上使用它时,去掉.keys;包含检查和迭代都已经使用了这些键


仔细想想,您可以拥有一个包含已知安全属性的class属性,然后在函数中检查该属性,并在实例上使用setattr。

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

def create(**kwargs):
    keys_ok = set(User.__dict__)
    user = User()
    for k in kwargs:
        if k in keys_ok:
            setattr(user, k, kwargs[k])
如果您确实需要覆盖继承的属性,可以使用自定义谓词帮助避免名称以下划线开头的成员或其他您希望确保的成员不能以这种方式设置


我也会考虑,如果SETKARWS—SETKEY SKOK不是空的,那么至少要发出警告——即,如果传递给创建的一些命名参数不能被设置为创建实例中的参数;那不可能是件好事-

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

def create(**kwargs):
    keys_ok = set(User.__dict__)
    user = User()
    for k in kwargs:
        if k in keys_ok:
            setattr(user, k, kwargs[k])
如果您确实需要覆盖继承的属性,可以使用自定义谓词帮助避免名称以下划线开头的成员或其他您希望确保的成员不能以这种方式设置


我也会考虑,如果SETKARWS—SETKEY SKOK不是空的,那么至少要发出警告——即,如果传递给创建的一些命名参数不能被设置为创建实例中的参数;那不可能是件好事-

实际上,声明性基类已经插入了您正在寻找的确切构造函数,如中所述。因此,只需执行Userusername=Carson,password=1234即可执行您想要的操作,而Usersomething\u not\u an\u attribute='foo'将引发异常。

事实上,声明性基类已经插入了您正在查找的确切构造函数,如中所述。因此,只需执行Userusername=Carson,password=1234即可执行您想要的操作,而Usersomething\u not\u an\u attribute='foo'将引发异常。

是的,我正在寻找一种方法,在写入类之前检查类中是否存在属性。在Python中是否有一种内置的方法来实现这一点?或者更好,在SQLAlchemy中只允许设置有效列?我想我可以创建一个dict,但我试图避免复制表结构。您可以使用hasattr查看对象是否具有给定的属性,但这不会阻止它们践踏对象的位。如果我检查属性的类型呢?在类定义中,列属性被设置为列对象-但是当我分配给它们时,我只是分配字符串。。。有魔法发生吗?检查属性是否为列有效吗?不幸的是,列很可能是一个描述符,它基本上是它返回的类型的黑框。我会在对象上查找其他列出有效字段名的内容;Django的ORM有这个,所以如果SQLAlchemy没有,我会感到惊讶。Django叫它什么?我只是不确定从哪里开始寻找,我已经检查了很多东西的dir输出,但它似乎没有真正导致任何地方是的,我正在寻找一种方法,在写入类之前检查类中是否存在属性。在Python中是否有一种内置的方法来实现这一点?或者更好,在SQLAlchemy中只允许设置有效列?我想我可以创建一个dict,但我试图避免复制表结构。您可以使用hasattr查看对象是否具有给定的属性,但这不会阻止它们践踏对象的位。如果我检查属性的类型呢?在类定义中,列属性被设置为列对象-但是当我分配给它们时,我只是分配字符串。。。有魔法发生吗?检查属性是否为列有效吗?不幸的是,列很可能是一个描述符,基本上是一个黑色的bo
x表示它返回的类型。我会在对象上查找其他列出有效字段名的内容;Django的ORM有这个,所以如果SQLAlchemy没有,我会感到惊讶。Django叫它什么?我只是不确定从哪里开始寻找,我已经检查了一堆东西的dir输出,但它似乎没有真正引导任何地方,从那里开始,init导入实际上为您提供了一个不同于包的模块。从中使用。在2.6+/3.x中导入或从包导入的名称导入。从初始化导入实际上为您提供了与包不同的模块。从中使用。在2.6+/3.x中导入或从包导入的名称导入。谓词是函数吗?就像一个过滤器?@Carson,它是一个函数,为你想要的成员返回一个真值,为你不想要的成员返回一个假值。过滤器是一种重载术语,例如,内置过滤器应用谓词选择序列中的某些项-因此它应用谓词,显然它不像谓词…!-所以你的第二个问题变得模棱两可,无法准确回答。我明白了。嗯,我最后写了一个这样的列表理解:[I for I in User.\uu dict\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuui?使用getmembers和lambda会更像pythonic吗?@Carson,如果不需要支持继承,那么查看_udict_uu就可以了——它甚至不查看从类的基和其他祖先继承的成员。inspect.getmembers遍历整个继承树以支持继承。如果您不关心继承,那么使用_dict__是可以的。谓词是函数吗?就像一个过滤器?@Carson,它是一个函数,为你想要的成员返回一个真值,为你不想要的成员返回一个假值。过滤器是一种重载术语,例如,内置过滤器应用谓词选择序列中的某些项-因此它应用谓词,显然它不像谓词…!-所以你的第二个问题变得模棱两可,无法准确回答。我明白了。嗯,我最后写了一个这样的列表理解:[I for I in User.\uu dict\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuui?使用getmembers和lambda会更像pythonic吗?@Carson,如果不需要支持继承,那么查看_udict_uu就可以了——它甚至不查看从类的基和其他祖先继承的成员。inspect.getmembers遍历整个继承树以支持继承。如果您不关心继承,那么使用_udict_;就可以了。