Python 使用**kwargs初始化类是否存在安全问题?

Python 使用**kwargs初始化类是否存在安全问题?,python,python-2.7,optimization,sqlalchemy,Python,Python 2.7,Optimization,Sqlalchemy,我最近开始在\uuu init\uuuu()中使用**kwargs来初始化对象,因为在添加另一个属性时,我不必对函数进行任何更新。我只是把它们作为参数传递,循环就完成了工作 class Customer(Base): """Model that defines a customer entity""" __tablename__ = "customers" date_created = Column(DateTime) date_modified = Colu

我最近开始在
\uuu init\uuuu()
中使用
**kwargs
来初始化对象,因为在添加另一个属性时,我不必对函数进行任何更新。我只是把它们作为参数传递,循环就完成了工作

class Customer(Base):
    """Model that defines a customer entity"""

    __tablename__ = "customers"

    date_created = Column(DateTime)
    date_modified = Column(DateTime)

    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)
但是,根据您的经验,这样做是否存在安全问题?与下面显式定义将初始化什么的代码相比,我们是否会遇到不必要的副作用

class Customer(Base):
    """Model that defines a customer entity"""

    __tablename__ = "customers"

    date_created = Column(DateTime)
    date_modified = Column(DateTime)

    def __init__(self, attrs):
        self.date_created = attrs.get("date_created")
        self.date_modified = attrs.get("date_modified")
这是否符合“不必要的副作用”

或者为了更有趣:

class Bar(object): 
    pass

f = Foo("Bob", __dict__={"aaa":1, "bbb":2, "name":"HEHEHE"}, __class__=Bar)
type(f)
>>> <class '__main__.Bar'>
类栏(对象):
通过
f=Foo(“Bob”,uuuu dict_uuuuu={“aaa”:1,“bbb”:2,“name”:“HEHEHE”},uuuuuuuu class=Bar)
类型(f)
>>> 

现在,只要只有可信代码实例化您的类,这里就没有真正的安全问题——实际上,所有这些都可以在初始化器之外完成。但是显式的代码更具可读性,并且有助于捕捉一些错误。

受Bruno的启发,您甚至可以覆盖
\uuuu getattribute\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

class Foo(object):
    def __init__(self, name, **kw):
        self.name = name
        for k, v in kw.items():
            setattr(self, k, v)

class Bar(Foo):
    def __getattribute__(self, name):
        return 'no way'   

    def __setattr__(self, name, value):
        print('aint gonna happen bro')    
为此:

>>> f = Foo("Bob", aaa=1, __class__=Bar)
>>> f.aaa
'no way'
>>> f.__class__
'no way'
你甚至无法修复它:

>>> f.__class__ = Foo
aint gonna happen bro
>>> f.__class__
'no way'

无论如何,这几乎就是所做的,只是它在设置之前检查类是否确实具有该属性。因此,只需删除自定义的
\uuuuu init\uuuuu
并使用。谢谢@IljaEverilä我在我的SQLAlchemy类中删除了自定义的
\uuuu init\uuuuu()
>>> f.__class__ = Foo
aint gonna happen bro
>>> f.__class__
'no way'