由买买提看人间百态

boards

本页内容为未名空间相应帖子的节选和存档,一周内的贴子最多显示50字,超过一周显示500字 访问原贴
Programming版 - mutating input argument不应该鼓励吧
相关主题
clojure和common lisp区别大么,语法上。从今天开始起,学C++!
1st class citizen怎么这里这么多人学python
经常看到一些名词:invariant, covariant, immutable关于FP
对 (im)mutability 的误解和深度理解Python Q: function pass in struct pointer, come back with data filled
FP更接近人的思维也谈OOP跟FP之争
newbie python questionOOP里面的Object其实是actor
花了一个小时学习了pythonpython 区别于其他语言的根本?
没人觉得python的string是immutable不爽吗?criticism of Scala
相关话题的讨论汇总
话题: dict话题: aval话题: key话题: py话题: arg
进入Programming版参与讨论
1 (共1页)
j********x
发帖数: 2330
1
mutating:
def foo(dict_arg):
dict_arg.pop("xxx")
if dict_arg == yyy:
# do something
non-mutating:
def foo(dict_arg):
if DictEqualExcept(dict_arg, yyy, "xxx"):
# do something
哪种比较好,需要其他细节我可以补充
d****i
发帖数: 4809
2
你这个两个貌似都没问题吧,就好比C里面经常有
int foo(struct Person *pp, const struct Name *pn);
前一个mutable(一般既是输入也是输出),后一个immutable(只是输入)。

【在 j********x 的大作中提到】
: mutating:
: def foo(dict_arg):
: dict_arg.pop("xxx")
: if dict_arg == yyy:
: # do something
: non-mutating:
: def foo(dict_arg):
: if DictEqualExcept(dict_arg, yyy, "xxx"):
: # do something
: 哪种比较好,需要其他细节我可以补充

j********x
发帖数: 2330
3
啥问题,mutate的应该有一个参数不mutate
不mutate的应该有个参数mutate?
p**o
发帖数: 3409
4
没有特别“不鼓励”。如果要对传入对象的内部状态进行变更,当然只能传入mutable
object。就算不变更,一般也是照样传进去。
如果你不完全信任你要调用的函数、要确保它无法更改你传入对象的状态(一般这会被
认为是不可思议的需求),可以转成immutable object传入,比如list转tuple,set转
frozenset,一般对象做deepcopy,当然这样就无谓地增加了overhead。

【在 j********x 的大作中提到】
: mutating:
: def foo(dict_arg):
: dict_arg.pop("xxx")
: if dict_arg == yyy:
: # do something
: non-mutating:
: def foo(dict_arg):
: if DictEqualExcept(dict_arg, yyy, "xxx"):
: # do something
: 哪种比较好,需要其他细节我可以补充

p**o
发帖数: 3409
5
对。有const关键字就可以解决这个问题。
python这样的动态语言简化了设计,但从函数签名看不出这个这个函数要不要对入参进
行变更,实际增加了心智负担。Python3引入function annotation可以缓解部分问题,
但不强制做类型检查,属于君子协定。

【在 d****i 的大作中提到】
: 你这个两个貌似都没问题吧,就好比C里面经常有
: int foo(struct Person *pp, const struct Name *pn);
: 前一个mutable(一般既是输入也是输出),后一个immutable(只是输入)。

p**o
发帖数: 3409
6
没怎么看明白。要不你把具体场景展开说一说?

【在 j********x 的大作中提到】
: 啥问题,mutate的应该有一个参数不mutate
: 不mutate的应该有个参数mutate?

j********x
发帖数: 2330
7
一个直接后果是,同样的参数,两次调用之间结果不同
而且根据这里的目的“忽略dict中某个key的值”进行比较;本身应该用直观的方法表
现,所谓pop之后再比较,理解起来并不容易。起码我本人看了3遍才明白

mutable

【在 p**o 的大作中提到】
: 没有特别“不鼓励”。如果要对传入对象的内部状态进行变更,当然只能传入mutable
: object。就算不变更,一般也是照样传进去。
: 如果你不完全信任你要调用的函数、要确保它无法更改你传入对象的状态(一般这会被
: 认为是不可思议的需求),可以转成immutable object传入,比如list转tuple,set转
: frozenset,一般对象做deepcopy,当然这样就无谓地增加了overhead。

p**o
发帖数: 3409
8
“同样的参数,两次调用之间结果不同”,一般指的是默认参数的问题,
感兴趣的话可以参考这个讨论:
http://www.newsmth.net/bbstcon.php?board=Python&gid=84864
但在你这个具体场景,并不是“同样的参数”,因为两次传入的对象的状态不一样(从
dict里面pop一对key-value出来是对原dict的变更)。
你的这个具体需求:“忽略dict中某个key的值”,为了不更改原dict,可以在函数里
把原dict拷贝一份再pop再比较啊。就是我前面说的。
In [18]: d1 = {1:11, 2:22, 3:33, 4:44}
In [19]: d2 = {1:11, 2:22, 3:33}
In [20]: d1a = d1.copy()
In [21]: d1a.pop(4)
Out[21]: 44
In [22]: d1a == d2
Out[22]: True
In [23]: d1
Out[23]: {1: 11, 2: 22, 3: 33, 4: 44}

【在 j********x 的大作中提到】
: 一个直接后果是,同样的参数,两次调用之间结果不同
: 而且根据这里的目的“忽略dict中某个key的值”进行比较;本身应该用直观的方法表
: 现,所谓pop之后再比较,理解起来并不容易。起码我本人看了3遍才明白
:
: mutable

j********x
发帖数: 2330
9
copy一次这种脱了裤子放屁的就算了。。。
p**o
发帖数: 3409
10

如果你嫌copy有开销,自己定制一个又不是难事:
def dict_equal_except (dict_a, dict_b, except_key):
assert except_key in dict_a
if len(dict_a) != len(dict_b) + 1:
return False
for key, aval in dict_a.iteritems():
if key != except_key and (key not in dict_b
or dict_b[key] != aval):
retur False
return True
但CPython循环一般比C慢2-3个数量级,dict不大时还不如直接copy。
参考 CPython 实现:
http://hg.python.org/cpython/file/2.7/Objects/dictobject.c
static int
dict_equal(PyDictObject *a, PyDictObject *b)
{
Py_ssize_t i;
if (a->ma_used != b->ma_used)
/* can't be equal if # of entries differ */
return 0;
/* Same # of entries -- check all of 'em. Exit early on any diff. */
for (i = 0; i <= a->ma_mask; i++) {
PyObject *aval = a->ma_table[i].me_value;
if (aval != NULL) {
int cmp;
PyObject *bval;
PyObject *key = a->ma_table[i].me_key;
/* temporarily bump aval's refcount to ensure it stays
alive until we're done with it */
Py_INCREF(aval);
/* ditto for key */
Py_INCREF(key);
bval = PyDict_GetItem((PyObject *)b, key);
Py_DECREF(key);
if (bval == NULL) {
Py_DECREF(aval);
return 0;
}
cmp = PyObject_RichCompareBool(aval, bval, Py_EQ);
Py_DECREF(aval);
if (cmp <= 0) /* error or not equal */
return cmp;
}
}
return 1;
}

【在 j********x 的大作中提到】
: copy一次这种脱了裤子放屁的就算了。。。
j********x
发帖数: 2330
11
倒不是开销问题 我一般试图简化函数约定
如果code base绝大部份函数都不修改参数 那一般情况下修改参数是不鼓励的
而且修改参数的比较方法对我来说不容易理解 开销在我这里不是大问题 输入都很小
100元素以内
1 (共1页)
进入Programming版参与讨论
相关主题
criticism of ScalaFP更接近人的思维
函数式语言是不是特别费系统资源?newbie python question
python一问,怎么实现这个函数花了一个小时学习了python
这么说吧,fp不是否定变量,而是控制变量的范围没人觉得python的string是immutable不爽吗?
clojure和common lisp区别大么,语法上。从今天开始起,学C++!
1st class citizen怎么这里这么多人学python
经常看到一些名词:invariant, covariant, immutable关于FP
对 (im)mutability 的误解和深度理解Python Q: function pass in struct pointer, come back with data filled
相关话题的讨论汇总
话题: dict话题: aval话题: key话题: py话题: arg