Are booleans mutable in python? - python

I have the following code in python:
def update(request, id):
success = 0
try:
product = Mattress.objects.get(id=id)
success = 1
except Mattress.DoesNotExist:
pass
if success == 1:
return render_to_response("success.html")
else:
return render_to_response('failure.html')
Is this code a valid way to check the "success" boolean. If the code passes through the try statement, will "success" be changed to 1 or is it remaining at 0?

Answering your question:
Are booleans mutable in python?
Yes and no. Variables that are assigned a boolean value are (probably always, and definitely in this case) mutable, yes. They're also not restricted to being assigned boolean values, as variables are not staticly typed.
But the booleans True and False themselves are not mutable. They are singletons that cannot be modified.
Looking at your actual code:
if success = 1:
Is not valid syntax, you want a == there. Also, idiomatically speaking you should not use 0 and 1 for success and failure values you should use True and False. So you should refactor to something like this:
def update(request):
success = False
try:
product = Mattress.objects.get(id=id)
success = True
except Mattress.DoesNotExist:
pass
if success:
return render_to_response("success.html")
else:
return render_to_response('failure.html')

Yes. success will be changed to 1 on success.

There are a few things wrong with this snippet.
Firstly, you're not using a boolean type. Python's booleans are True and False.
Second, you're not comparing in your if statement. That line isn't valid in Python 3. What you're looking for is: if success == 1: or if success == True:
You would still be able to assign a boolean value to a variable regardless of boolean immutability. I believe they are stored as a primitive type, so they're as immutable as any other primitive type.

You should consider using an actual boolean and not an integer. You can set success to true or false and Python will interpret them as keywords to the values of 1 and 0. Using numbers can be a bit tricky as some languages interpret things different. In some languages 0 is false but any value besides 0 is considered true. However the answer to your question is yes, it will work just fine.

Probably the question you are asking is not even related with the problem you are trying to solve. I think there is a a Pythonic way to achieve what you want by:
def update(request):
try:
product = Mattress.objects.get(id=id)
except Mattress.DoesNotExist:
template_name = 'failure.html'
else:
template_name = 'success.html'
return render_to_response(template_name)
Basically if the exception is thrown, i.e., the template you will render will be 'failure.html'. On the other hand, if the query is performed successfully, 'success.html' will be rendered.

Related

Is it better to use 'elif' or consecutive 'if' statements alongside return statements?

This question is specifically regarding coding convention. I know that using if or elif in this case will produce the same results. Just wondering which is the "proper" way to construct this function:
With consecutive if:
def can_take(self, selectedCourse):
if selectedCourse.hasPassed():
return False
if selectedCourse.getPrereqs() != 'none':
for prereq in selectedCourse.getPrereqs():
if not self.courses[prereq].hasPassed():
return False
return True
With elif:
def can_take(self, selectedCourse):
if selectedCourse.hasPassed():
return False
elif selectedCourse.getPrereqs() != 'none':
for prereq in selectedCourse.getPrereqs():
if not self.courses[prereq].hasPassed():
return False
return True
If I had to choose between the two, I would probably use two if statements, but that's just a matter of personal preference.
If I had a third choice, I wouldn't have any return statements with Boolean literals. I would write a single return statement that uses and and or.
return (not selected.hasPassed()
and (selected.getPrereqs() == 'none'
or all(x.hasPassed()
for x in selected.getPrereqs()))
This is close to how you would describe this in English: you can take the class if you have not passed it, and if the class either has no prerequisites or if you have passed all the prerequisites.
As John Kugelman points out, if getPrereqs returned an empty list instead of 'none', you could further reduce this to
return (not selected.hasPassed()
or all(x.hasPassed()
for x in selected.getPrereqs())
I love the early return pattern:
Get invalid cases out of the way first, either simply exiting or raising exceptions as appropriate, put a blank line in there, then add the "real" body of the method. I find it easier to read.
Returning early keeps the nesting level down, which is great way to reduce cognitive load. I would take it one step further and flip the second if statement around so it too returns early:
def can_take(self, selectedCourse):
if selectedCourse.hasPassed():
return False
if selectedCourse.getPrereqs() == 'none':
return True
for prereq in selectedCourse.getPrereqs():
if not self.courses[prereq].hasPassed():
return False
return True
That said, some other improvements I would make:
Avoid stringly typed variables. Switch that 'none' to None.
But then, when a method returns a list don't return None when there are no results. Return an empty list. Then the caller can blindly iterate over the list without checking if it's None or empty.
def can_take(self, selectedCourse):
if selectedCourse.hasPassed():
return False
for prereq in selectedCourse.getPrereqs():
if not self.courses[prereq].hasPassed():
return False
return True
If you're comfortable with generator expressions you could even convert the loop into an all(...) call, removing the need for the final return True.
def can_take(self, selectedCourse):
if selectedCourse.hasPassed():
return False
return all(self.courses[prereq].hasPassed()
for prereq in selectedCourse.getPrereqs())
I like this because it's a more direct encoding of the question: "Has the student passed all of the prereqs?"
I think I prefer the first version. Why? When you have an if...elif...elif... thing with returns in each branch, there are two "competing" control structures: the if statement and the returns. Obviously, the returns will "win", so we might as well remove the elif stuff. Either that, or have just one return statement, which returns a value computed by a preceding if...elif...elif...else structure.
We use elif but please understand it depends on your problem statement.
Note: Please do not create a big ladder out of it as then it becomes difficult to maintain and debug the code.

How to check if an attribute is True in Python

I want to look if an object.est_devoilee is True : I need to make conditions.
If object.devoiler is True : do that.
If object.devoiler is not True: do that.
At first, my objet have self.est_devoilee = False and when I use object.devoiler, it becomes self.est_devoilee = True with that def :
def devoiler(self):
self.est_devoilee = True
I have tried
if object.devoiler() == True:
I have tried
if case.devoiler() is not True:
But I feel it's not really checking if self.est_devoilee have been used before. It's as if it always returns true because def devoiler(self): does not return a boolean? I only want to check if object.est_devoilee = True but I don't know how!
Sorry for my spelling, I am french. Thank you!
The devoiler() method is not used to get the value of the attribute, it just sets it to True. If you want to check it, just access the attribute:
if case.est_devoiler:
# do something

What is the difference between None and boolean (True, False) in python's default argument values?

In function definitions, one can define a boolean default argument's values as argument=None or argument=False.
An example from pandas concat:
def concat(
objs,
axis=0,
join="outer",
join_axes=None,
ignore_index=False,
keys=None,
levels=None,
names=None,
verify_integrity=False,
sort=None,
copy=True,
):
While both usages can be found, why would one be using one over the other?
Is there any PEP on this?
True and False are specific bool values. Use default False when you have a bool field and you want the default to be False.Don't use False as a value for a non-bool field.
None is used as a generic placeholder when the value will be set later. It can be typed as Optional[T], which is equivalent to Union[T, None].
You might be thinking of None and False as similar because they're both "falsy" (bool(x) returns False), but the same is true of several other values, [] () {} 0 0.0, etc and we don't use them like None either.
In your example, True/False are used where the field takes a boolean value. None is used where the field takes an Optional[List]. (The exception is sort: Optional[bool], which is being used temporarily as an ad-hoc compatibility tool for a deprecated behavior.)
True and False are boolean values, so in this context None can make sense if you have a boolean variable that can be in an 'unknown' state. Strictly spoken, such a variable would not be boolean, but in reality, this can be quite handy.
For example:
# In the beginning, we simply don't know if it's true or not
is_cat_alive = None
# But later we will determine the status
is_cat_alive = check_cat_in(box)
Note that if you are using a boolean like this, then if is_cat_alive will be false when is_cat_alive is either False or None which makes sense but might not be what you want to know. So to explicitly check for a dead cat, you would have to use if is_cat_alive == False.
None is similar to a null value if you know anything about those. Someone might say it's equal to 0, but None means that it is nothing. Say age = None for example. age is a variable, but it is equal to nothing. False is an actual value. True and False can be used as an indicator such as
def name_check(name)
if name == "Brittany":
return True
else:
return False
Calling that function with "Brittany" as the name parameter would return True which could be used in other conditions as well. Hope this helped! Good luck!
Look at the following code:
my_string = ''
my_other_string = None
my_final_string = 'I am a string'
If you were using these within python in something like an if statement they would actually equal the following:
my_string = False
my_other_string = None
my_final_string = True
Hope that helps

Why doesn't None put in variable?

Why doesn't None put in variable?
I wrote in code like
def check(request):
if len(request.POST.get('access_key')) >= 25:
return HttpResponse('<h1>Hello</h1>')
elif request.POST.get('access_key', None) == None:
id_json = {}
return JsonResponse(id_json, safe=False)
else:
return HttpResponse('<h1>Good</h1>')
Now I put anything to access_key in POSTMAN like
I think in this case the program goes into elif request.POST.get('access_key', None) == None:,but now it goes into else:.
I really cannot understand why the null value is not recognized as None. I wrote print(type(request.POST.get('access_key'))) and blank is printed out.
I wanna make a system if no value is put, and the program should go into elif request.POST.get('access_key', None) == None:.
How should I fix this?
The return value of request.POST.get('access_key') is '', which is not None.
Try to check for elif not request.POST.get('foo'), this will catch both cases, because both, `` and None will evaluate to False.
Actually, all three values ('', None, and False) as value will fulfill the if condition if not value:.
Have a look at this wiki page: https://en.wikipedia.org/wiki/Empty_string
In most programming languages, the empty string is distinct from a null reference (or null pointer) because a null reference does not point to any string at all..
And more precisely for Python: https://docs.python.org/2/library/constants.html
The sole value of types.NoneType. None is frequently used to represent the absence of a value, as when default arguments are not passed to a function.
your request.POST.get('access_key') is equal ''
so instead of
elif request.POST.get('access_key', None) == None:
try simple
elif not request.POST.get('access_key'):

Testing to see if IPv4 address is valid

I want to return a boolean depending if the address given is a correct IPv4 address or not. I am having an issue with the all() built in in python. I have looked up the documentation on it and it seems straight forward. That being said I can't get it to work for my expression. If you could explain how it works layman's terms and how I could correct my code, that would be great.
def IPv4_address(address):
lst_split_address = address.split(".")
slice_split_address = [int(num) for num in lst_split_address[1:]]
if address.count(".") != 3:
return False
elif address == "":
return False
else:
if all(slice_split_address) >= slice_split_address[0]:
return True
else:
return False
print IPv4_address("10.20.30.40")
As said in the documentation of all, it checks if every element in a list evaluates to True (basically bool(e) is True) or it is empty.
Now you have a list of integers in slice_split_address and so it'll check if every element of that list evaluates to True if you just call it like you do and any number other than 0 will evaluate to True, but an IP like 127.0.0.1 is actually valid.
So what you need is actually a list which contains True if the corresponding number is between 0 and 255 (inclusive):
is_valid = [0 <= e <= 255 for e in slice_split_address]
If you call then all(is_valid) it returns if every item in slice_split_address is between 0 and 255. Usually it'll be combined into something like all(0 <= e <= 255 for e in slice_split_address).
Now there is still one issue in your implementation because slice_split_address doesn't actually contain the first number of the IP address, so you might include it. Or do you actually want the first number to be lower or equal to the other three numbers?
Also your check all(…) >= … doesn't make sense as all() only returns True or False so comparing it with an integer doesn't really make sense.
Note that all(is_valid) will also return True to IP addresses like 0.0.0.0 so might need to adjust the range I used.
If you are using Python3, there is a built-in ipaddress module that you can use.
As for what is wrong with your code, I don't believe that the all() function does what you think it does. all() expects an iterable of Booleans, and returns True if every one of those Booleans is True.
To get that to work how you expected, you probably want something like
all(addr_piece >= slice_split_address[0] for addr_piece in slice_split_address)
Don't reinvent the wheel (unless you're happy to maintain the wheel). You can use a regex to validate ipv4 addresses. The following pattern is taken from Django:
r'(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}'
If you are working already in the context of a Django project, you may prefer to just import their validator and use it directly:
from django.core.validators import validate_ipv4_address
As others have said, there are better ways to do this. And your algorithm doesn't actually validate IPv4 addresses. But here's a repaired version of your code.
def IPv4_address(address):
if address.count(".") != 3:
return False
elif address == "":
return False
else:
lst_split_address = address.split(".")
slice_split_address = [int(num) for num in lst_split_address[1:]]
head = slice_split_address[0]
return all(u >= head for u in slice_split_address)
print IPv4_address("10.20.30.40")
output
True
I've moved the lst_split_address stuff into the else block because there's no need to do it if the if / elif parts return False.
all(u >= head for u in slice_split_address)
uses a simple generator expression to check that all items in slice_split_address are >= the head item.

Categories