目前不习惯Python不能重载构造函数的问题

2013-07-08 15:51:23 +08:00
 banxi1988
一般来说这不是问题。
Python有魔法的*args和**kwargs。
我的问题来自于,
我有一些Model类。
有时候它需要使用dict来创建。如从request.form之类。
有时候自己手动写参数创建。
当从request.form创建的时候,
我希望构造函数是这样的:
(1)使用字典作为参数
def __init__(self,form):
if not isinstance(form,dict):
continue
pass

但是当我自己手动传参数时,我希望它是这样的:
(2)使用关键词参数。
def __init__(self,**values):
pass



在我没有找到好的解决方法之前:
我是使用第二种形式的。如果是处理form的话我就
Model(**form.to_dict())

这个**这种魔法看起来不是很好,折包又打包(指实参数的**kw和形参的**kw)
而且像我一般都有一个ModelMixin来处理
从dict到model对象赋值的通用方法:
def _init_inner(self, **params):
if not isinstance(params, dict):
return
for col in self.__table__.columns:
name = col.name
# 不设置键值,和密码(要做特别的处理)
if name in ('id', 'password',) or '_id' in name:
continue
value = params.get(name)
if value:
if isinstance(col.type, db.Integer):
value = int(value)
elif isinstance(col.type, db.Boolean):
value = bool(value)
setattr(self, name, value)
这样的话,
__init__()
里面还需要再一次的
self._init_inner(**kw)

这样经过多次的打包折包我觉得需要改改了。
求指导。
大家的model实例化是怎么做的呢?
11004 次点击
所在节点    Python
7 条回复
timonwong
2013-07-08 16:10:20 +08:00
# 非要如此的话:

class Model(object):
def __init__(self, *args, **kwargs):
if args:
assert len(args) == 1
assert isinstance(args[0], dict)
self._init_models(args[0])
else:
self._init_models(kwargs)

def _init_models(self, model_dict):
# YOUR LOGIC
pass
banxi1988
2013-07-08 16:17:27 +08:00
@timonwong 嗯,看起来不错。多谢
binux
2013-07-08 16:18:26 +08:00
这是应该你自己判断的
如果调用Model(form={a:1}),你的意思是调用__init__(self,form)呢,还是调用__init__(self,**values) ?
banxi1988
2013-07-08 16:43:41 +08:00
@binux 其实就是,
手动的时候,Model(name='wowow',age=12)这样简单明了,
但是从form中构造的话,
使用Model(form)比较直接。
Xe0n0
2013-07-08 17:26:37 +08:00
重新写个 dict_to_model 不就可以了,比如类方法。构造函数一般是为了处理构造时必须要初始化的东西,比如 C++ 中分配内存,子对象之类。这部分任务在 Python 中相对较少。

C++ 中的那种重载后变成实际上调用不同函数的行为在 Python 是不存在的。一部分原因是没有静态类型,一部分用简单的默认参数和 args, kwargs 就可以解决。楼上说的也就是手动实现了一遍类型检查而已。

完全不需要生硬寻找相同的实现方式。
banxi1988
2013-07-08 17:36:58 +08:00
@Xe0n0 有道理。
Python中也可以使用这种工厂方法的模式。SQLAlchemy的字段是类级别的。。
用类方法也不错。谢谢了。
banxi1988
2013-07-08 18:39:24 +08:00
@timonwong
突然想起来,Python中的dict就有类似的构造器。
dict() -> new empty dictionary
dict(mapping) -> new dictionary initialized from a mapping object's
(key, value) pairs
dict(iterable) -> new dictionary initialized as if via:
d = {}
for k, v in iterable:
d[k] = v
dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)



@Xe0n0 感觉使用默认的构造方法如dict中使用的,感觉更自然点呢?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/75139

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX