Установка атрибутов класса во время строительства от ** kwargs

StackOverflow https://stackoverflow.com/questions/2926593

Вопрос

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() Мне немного глупо, и мне интересно, есть ли лучший способ сделать это, что не требует лестницы, если не удастся, если будут добавлены какие-либо ключи, которые не будут в объекте пользователя. Нравиться:

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

Таким образом, я мог бы поставить это в свою собственную функцию (если только один, надеюсь, уже не существует?) Итак, мне не пришлось бы сделать, если бы лестница снова и снова, и поэтому я мог бы изменить структуру стола, не модифицируя этот код.

Какие-либо предложения?

Это было полезно?

Решение

Мое предложение не будет упростить его дальше. Вы рискуете наступить на важные объектные структуры, если вы назначаете произвольные атрибуты.

Одно упрощение, которое я бы сделал, это упасть .keys() Когда вы используете его на диктографии; Оба проверки сдерживания и итерация уже используют ключи.

...

На второй мысли у вас может быть атрибут класса, который содержит известные безопасные атрибуты, а затем проверьте этот атрибут в функции и использовать setattr() на экземпляре.

Другие советы

На самом деле декларативный базовый класс уже вставляет точный конструктор, который вы ищете, как документировано в декларативные модули документы. Отказ Так что просто делать 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 с атрибуция
Не связан с StackOverflow
scroll top