Установка атрибутов класса во время строительства от ** kwargs
-
05-10-2019 - |
Вопрос
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
не можем быть установлены в качестве аргументов в созданном экземпляре; Это не может быть хорошей вещью ...! -)