我有allowed = ['someoption','someother']
,
和default = 'default_value'
v
来自用户输入。
然后当我这样做:
v = v if v.lower() in allowed else default
,按预期工作,
v
仅在allowed
列表中列出的用户指定选项中取值,否则设置为default_value
。
但是,我希望通过定义验证来将验证分离为函数:
def validate(value, rules, default)
value if value.lower() in rules else default
,但现在当我validate(v, allowed, default)
时,尝试在allowed
列表中输入值而不是,而不是让v
按住default_value
我得到了什么。
所以我希望将v
作为参考传递并进行更改,但这并没有发生。我该怎么做才能得到预期的结果?
答案 0 :(得分:2)
首先,对validate
函数的小修正:
def validate(value, rules, default)
return value if value.lower() in rules else default
然后只需将值分配给结果
v = "something"
allowed = ["someoption", "someother"]
default = "default_value"
v = validate(v, allowed, default)
保持简单。
关于“通过引用传递” - Python没有这个概念。如果你传入一个函数不可变类型的值(比如一个字符串),它就会被称为“按值”。如果你传入可变对象(如列表),它就会被称为“通过引用”。没有办法,你会指示Python改变这样做的方式。
如果你真的坚持修改传入的结果,这种(丑陋的)方式可以起作用:
>>> def ugly_validate(value_lst, rules, default):
... if value_lst[0].lower() not in rules:
... value_lst[0] = default
...
>>> v = "something"
>>> allowed = ["someoption", "someother"]
>>> default = "default_value"
>>> v_lst = [v]
>>> ugly_validate(v_lst, allowed, default)
>>> v_lst
['default_value']
>>> v = "someoption"
>>> v_lst = [v]
>>> ugly_validate(v_lst, allowed, default)
>>> v_lst
['someoption']
>>> allowed_dct = {key: key for key in allowed}
>>> allowed_dct
{'someoption': 'someoption', 'someother': 'someother'}
>>> res = allowed_dct.get(v, default)
>>> res
'someoption'
>>> v = "unknown"
>>> res = allowed_dct.get(v, default)
>>> res
'default_value'
>>> class AllowedValues():
... def __init__(self, allowed_values, default):
... self.allowed_values = allowed_values
... self.default = default
... def get(self, value):
... if value.lower() in self.allowed_values:
... return value
... else:
... return self.default
...
>>> allowed
['someoption', 'someother']
>>> judge = AllowedValues(allowed, default)
>>> v = "someoption"
>>> v = judge.get(v)
>>> v
'someoption'
>>> v = "unknonw"
>>> v = judge.get(v)
>>> v
'default_value'
答案 1 :(得分:1)
在Python中,所有内容都通过asssigment传递。在您的情况下,value
名称被指定为v
指向的同一对象,但只要您更改value
,因为它指向的(字符串)是不可变的,它实际上是指向一个新的字符串对象,而不再指向v
指向的对象。
执行您要执行的操作的最佳方式是validate
函数返回新值(如果它不在rules
中。
或者(但不推荐),如果您使v
指向包含用户输入字符串的list
,那么由于list
s是可变的,因此更改为列表内部validate
功能也将是"可见"在那个功能之外。