I have allowed = ['someoption','someother']
,
,and default = 'default_value'
v
comes from user input.
then when I do :
v = v if v.lower() in allowed else default
, it works as expected,
v
is taking values only if user specified option listed in allowed
list, else is set to default_value
.
However, I wanted to isolate validation into function by defining it like:
def validate(value, rules, default)
value if value.lower() in rules else default
, but now when I do validate(v, allowed, default)
, and try to enter value not in allowed
list, instead of getting v
hold the default_value
, I get whatever I entered.
So I expected for v
to be passed as reference and being changed, but that did not happened. What should I do, to get the expected result?
First, small correction to your validate
function:
def validate(value, rules, default)
return value if value.lower() in rules else default
and then simply assign the value to your result
v = "something"
allowed = ["someoption", "someother"]
default = "default_value"
v = validate(v, allowed, default)
Just keep it simple.
Regarding "pass by reference" - Python does not have this concept. If you pass into a function immutable type of value (like a string), it goes in the way which could be called "by value". If you pass in mutable object (like list), it goes in the way which could be called "by reference". There is no way, you would instruct Python to change how this is done.
If you would really insist on modifying the result being passed in, this (ugly) way could work:
>>> 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'
In Python everything is passed by asssigment. In your case, the value
name is assigned the same object that v
is pointing to but as soon as you change value
, since what it is pointing to (a string) is immutable, it actually atarts poonting to a new string object and no longer to what v
Is pointing to.
The best way to do what you want to do is for the validate
function to return the new value (if it's not in rules
.
Alternatively (but not recommended), if you make v
point to a list
containing the user-entered string, then since list
s are mutable, the change to the list inside the validate
function will also be "visible" outside of that function.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.