What is the pythonic way of checking if multiple sub strings are present in the string?
For eg. I'm doing poll and check on the download status through API. The API returns status as "Download complete", "x% Downloaded" or "Installing".
Now, I want to check if 'downloaded' and 'installing' strings are present in status returned by API and if not, raise exception. I have implemented this by very novice way.
if api_object.status == 'Download Complete' :
break
elif 'Downloaded' in api_object.status.split():
time.sleep(interval)
elif 'Downloaded' not in api_object.status.split() or \
'Installing' not in api_object.status.split():
raise Exception("Error")
I would like to know any better approaches for comparison.
Thanks in advance.
A slightly more compact version:
if api_object.status == 'Download Complete':
break
elif 'Downloaded' in api_object.status:
time.sleep(interval)
elif 'Installing' not in api_object.status:
raise Exception("Error")
I don't know if your code is "pythonic" or not, but it is easy to understand and that's what matters most, even if it is a bit longer. Check the following "more pythonic" way:
....
elif all([(x not in status) for x in ['Downloaded', 'Installing'] ]):
....
does it read better?
How about:
status = api_object.status.partition(" ");
try:
action = {
"Downloaded": doA
"Complete": doB
"Installing": doC
}[status[2] or status[0]]
except KeyError:
# unknown status
raise
action();
Using a dict is a common idiom in python to replace a missing switch-statement. doA through doC shall be callables, which you call in the last line. Using the partition(sep) method and the or operator, one can easily pick the correct part of the string: If it exists, one gets the part behind the space, otherwise one gets the whole string.
One should note though, that caching the dictionary might be useful in a performance critical application to safe time for hashing the keys and building the dict.
For case insensitive matching, one would call lower() on the status string (before partition) and put the keys to lower case.
In this particular case, a break is required. One could do this by allowing the callable to return a boolean value, which, if True, triggers a break or a similar approach.
Here is my code :
if 'Download Complete' == api_object.status:
break
if 'Installing' == api_object.status:
continue
if api_object.status and api_object.status.endswith('Downloaded'):
time.sleep(interval)
else:
raise Exception("Error")
Related
I want to find out what content_type I'm about in my function but I'm Unable to reach the "got me" print statement no matter how I design my if statement. I also tried to use pprint to get the naming of the content_type but with no effect till now.
def mark_refunded(modeladmin, request, queryset):
queryset.update(status=2)
transactions = queryset.all()
for transaction in queryset.all():
print(transaction)
transaction.sender.acc_usd_balance += float(transaction.amount)
transaction.sender.save()
transaction.receiver.acc_usd_balance -= float(transaction.amount)
transaction.receiver.save()
print(transaction.content_type)
if transaction.content_type == "App | Sell Type A":
print("got me")
It seems that I'm unable to compare the output of print(transaction.content_type) with the if statement, why that?
I would expect that the output is the same value that I ask for at the if statement.
Assuming content_type is a foreign key, you'd need to compare if str(...) == ....
However, the more important issue here is that multiple concurrent requests will eventually absolutely surely corrupt those account balances since you're not managing them in an atomic way.
I was recently trying to solve a challenge on Hackerrank which asked us to figure out whether a string containing brackets (e.g. {}, (), and [] ) was balanced or not (source: https://www.hackerrank.com/challenges/balanced-brackets). I wanted to solve this using the following approach that also integrated the initial format Hackerrank provided:
import sys
def isBalanced(s):
#insert code here
if __name__ == "__main__":
t = int(raw_input().strip())
for a0 in xrange(t):
s = raw_input().strip()
result = isBalanced(s)
print result
I should also note that site has configured the following as being the standard input in order to test the functionality of the code:
3
{[()]}
{[(])}
{{[[(())]]}}
In order to get the following output:
YES
NO
YES
However, I didn't understand how to approach this code, chiefly because I did not understand why Hackerrank used the if __name__ == "__main__": clause, as I thought that this clause was only used if someone wanted their module to be executed directly rather than executed through being imported in another script (source: What does if __name__ == "__main__": do?). I also did not understand the for loop containing for a0 in xrange(t): since a0 is not used within the for loop for anything, so I'm really unsure how the standard input would be processed.
So I ended up looking up the solution on the discussion page, and here it is below:
lefts = '{[('
rights = '}])'
closes = { a:b for a,b in zip(rights,lefts)}
def valid(s):
stack = []
for c in s:
if c in lefts:
stack.append(c)
elif c in rights:
if not stack or stack.pop() != closes[c]:
return False
return not stack # stack must be empty at the end
t = int(raw_input().strip())
for a0 in xrange(t):
s = raw_input().strip()
if valid(s):
print 'YES'
else:
print 'NO'
This code also confuses me, as the writer claimed to utilize a data structure known as a "stack" (although it seems to be just a Python list to me). And although the writer removed the if __name__ == "__main__": statement, they retained the for a0 in xrange(t):, which I'm not sure how it processes the standard input's integer and corresponding strings.
Furthermore, although the isBalanced function confuses me because it returns not stack. In a hash comment on the return statement of the function, the writer also states the # stack must be empty at the end. What does that mean? And how could this list be empty if, during the clause if c in lefts:, the stack is appended with the character of the string that is being iterated in the for-loop. So why would the function return not stack? Wouldn't it be consistent to return True so that the function would act as a Boolean tester (i.e. would return true if a certain object adhered to certain criteria, and false if the the object did not)?
I am still relatively new to coding so there are a lot of principles I am not familiar with. Can anyone illuminate as to how this would work?
iam not sure how your code works .. if name == "main": do?). just exlained where you use of Before executing the code, it will define a few special variables. For example, if the python interpreter is running that module (the source file) as the main program, it sets the special name variable to have a value "main". If this file is being imported from another module, name will be set to the module's name
When I want to select objects with a get() function like
personalProfile = World.objects.get(ID=personID)
If get function doesn't return find a value, a "matching query does not exist." error occurs.
If I don't need this error, I'll use try and except function
try:
personalProfile = World.objects.get(ID=personID)
except:
pass
But I think this is not the best way since I use
except:
pass
Please recommend some idea or code sample to fight with this issue
That depends on what you want to do if it doesn't exist..
Theres get_object_or_404:
Calls get() on a given model manager, but it raises Http404 instead of the model’s DoesNotExist exception.
get_object_or_404(World, ID=personID)
Which is very close to the try except code you currently do.
Otherwise theres get_or_create:
personalProfile, created = World.objects.get_or_create(ID=personID)
Although, If you choose to continue with your current approach, at least make sure the except is localised to the correct error and then do something with that as necessary
try:
personalProfile = World.objects.get(ID=personID)
except MyModel.DoesNotExist:
raise Http404("No MyModel matches the given query.")
The above try/except handle is similar to what is found in the docs for get_object_or_404...
A get_or_none() function has been proposed, multiple times now. The rejection notice is feature creep, which you might or might not agree with. The functionality is present --with slightly different semantics-- in the first() queryset method.
But first things first:
The manager throws World.DoesNotExist, a specialized subclass of ObjectDoesNotExist when a World object was not found:
try:
personalProfile = World.objects.get(ID=personID)
except World.DoesNotExist:
pass
There's also get_object_or_404() which raises a Http404 exception when the object was not found.
You can also roll your own get_or_none(). A possible implementation could be:
def get_or_none(queryset, *args, **kwargs):
try:
return queryset.get(*args, **kwargs)
except ObjectDoesNotExist:
return None
Note that this still raises MultipleObjectsReturned when more than one matching object is found. If you always want the first object regardless of any others, you can simplify using first(), which returns None when the queryset is empty:
def get_or_none(queryset, *args, **kwargs):
return queryset.filter(*args, **kwargs).first()
Note however, for this to work reliably, you need a proper order for objects, because in the presence of multiple objects first() might be non-deterministic (it probably returns the first object from the database index used to filter the query and neither indexes not the underlying tables need be sorted or even have a repeatable order).
Use both, however, only when the use of the object to retrieve is strictly optional for the further program flow. When failure to retrieve an object is an error, use get_object_or_404(). When an object should be created when it does not exist, use get_or_create(). In those cases, both are better suited to simplify program flow.
As alasdair mentioned you could use the built in first() method.
It returns the object if it exists or None if it's not
personalProfile = World.objects.filter(ID=personID).first()
I came across Django request.session; I know how to set and test it for a specific value.
request.session['name'] = "dummy"
and somewhere I check
if request.session['name'] == "dummy" :
#do something
But, now I have to check whether the session variable was even set in the first place? I mean how can I check whether there exists a value in the request.session['name'] is set?
Is there a way to check it?
Treat it as a Python dictionary:
if 'name' in request.session:
print request.session['name']
How to use sessions: Django documentation: How to use sessions
get will do all the work for you. Check if the key exists, if not then the value is None
if request.session.get('name', None) == "dummy":
print 'name is = dummy'
Another way of doing this is put it in try.
In this the third example code snippet
if you apply del operation in a session variable it which does not exist, so it throws KeyError.
so check it like this.
try:
print(request.session['name'])
except KeyError:
print('name variable is not set')
I have a list of Account objects in self.accounts, and I know that only one of them will have a type attribute equal to 'equity'. What is the best (most pythonic) way to get only that object from the list?
Currently I have the following, but I'm wondering if the [0] at the end is superfluous. Is there a more succinct way to do this?
return [account for account in self.accounts if account.type == 'equity'][0]
return next(account for account in self.accounts if account.type == 'equity')
or
return (account for account in self.accounts if account.type == 'equity').next()
"Pythonic" means nothing. There is probably not any more "Succinct" solution than yours, no.
Ignacios solution has the benefit of stopping once it finds the item. Another way of doing it would be:
def get_equity_account(self):
for item in self.accounts:
if item.type == 'equity':
return item
raise ValueError('No equity account found')
Which perhaps is more readable. Readability is Pythonic. :)
Edit: Improved after martineaus suggestions. Made it into a complete method.
It's such a common need in Python but afaik there is no built in way to do it. You could also do:
return next(filter(lambda x: x.type == 'equity', self.accounts))